diff --git a/search/search_index.json b/search/search_index.json
index 66c6f784ff..28434360e4 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Gothic Modding Community page","text":""},{"location":"#welcome-to-gothic-modding-community-page","title":"Welcome to Gothic Modding Community page","text":"This GitHub page is designed to contain community maintained set of articles, tutorials and documentation for everything Gothic.
Info
The content here is not meant to be taken as the holy word of modding. We are just modders sharing our experiences, knowledge and our favorite work flows.
Discord Server
If you have any modding related questions, or just want to talk join our discord server.
Discord
Contribution
Feel free to open a pull request with your article or propose changes. Here is detailed contribution guide.
How to Contibute
Gothic Archive
First two Gothic games use engine called ZenGin, developed by Piranha Bytes and Mad Scientists. If you want to know more about the history of the development, there is a heap of information on the Gothic Archive.
Gothic Archive
Repository
Check out our GitHub repository for the site's source code and updates.
GitHub
"},{"location":"notready/","title":"None","text":"Warning
Sorry, this page is not ready yet!
"},{"location":"preferences/","title":"Preferences","text":""},{"location":"preferences/#preferences","title":"Preferences","text":"This page allows to set various preferences for reading the docs:
"},{"location":"preferences/#color","title":"Color","text":"You can change the feel of the site with a color change.
Select accent color:
Select hue color:
Reset colors
"},{"location":"preferences/#font","title":"Font","text":"You can change the font to another preset.
Select font: Default OpenDyslexic
"},{"location":"preferences/#custom-css","title":"Custom CSS","text":"You can add custom stylesheets. Input CSS:
"},{"location":"contribute/","title":"How to contribute","text":""},{"location":"contribute/#how-to-contribute","title":"How to contribute","text":"The Gothic Modding Community is a community-driven project. We encourage people to contribute.
This site is built with a Static Site Generator MkDocs and the Material for MkDocs theme together with multiple other MkDocs plugins.
Prerequisites for contribution differ based on the scale and type of the contribution.
"},{"location":"contribute/#feedback","title":"Feedback","text":"Using English, you can either open an issue via GitHub or join us on Discord.
"},{"location":"contribute/#direct-contribution","title":"Direct contribution","text":"Direct contribution is made via creating a copy of this repository (a fork) and creating a pull request (PR) on GitHub with changes for approval.
Don't waste time
Please make sure that the content you are contributing does not already exist on the dev page. You can use the search tool to filter GMC for different keywords and contents.
How to edit the source files?
The source files for the articles are written using the Markdown .md
file format (Markdown cheatsheet). Other than that, this site also uses Python Markdown Extensions which add more syntax rules like indented admonitions.
"},{"location":"contribute/#minor-changes","title":"Minor changes","text":"Minor changes like fixing typos, grammatical errors or removing/adding words to paragraphs in a single file can be done quickly with the button in the upper right corner of each article. This will open up a GitHub editing interface which will create a fork with a patch branch after modifying the file and guide the user to open up the pull request.
Select the correct branch for the pull request
Make sure that the pull request is directed towards the dev
or a special pre-merge
branch and not the main
branch.
"},{"location":"contribute/#major-changes","title":"Major changes","text":"More elaborate changes like editing multiple files at once, adding new articles, images, other miscellaneous files or changing the configuration of the page are easier to make via external tools on your local PC. While most of these operations can be done with the GitHub interface, it is rather cumbersome, and it may be harder to spot issues during the process as changes are not immediately visible in the browser in their final form.
Some preparation is needed before working on the files as MkDocs requires an installation of Python on the system to run. GitHub works on top of git so an installation of git is also required. A basic familiarity with Terminal/Command Prompt/Powershell command line interfaces is helpful.
"},{"location":"contribute/#system-setup-video","title":"System setup (video)","text":"Firstly, you should install Python. You can follow this step-by-step tutorial for Windows or macOS on how to install Python.
This video is from 2017?!
The process of installing Python hasn't changed since that point. However, please install the latest version of Python 3.
To work remotely with GitHub, you can install the latest version of git on your system following this tutorial.
If you just plan on editing the content of the articles with Markdown, you can simply install the latest version of Visual Studio Code for GUI git management and Markdown preview or work with any other familiar text editor and omit the environment setup.
If you are planning to do some elaborate Python programming, you can follow this step-by-step tutorial for Windows or macOS on how to set up an environment with Visual Studio Code.
"},{"location":"contribute/#system-setup-text","title":"System setup (text)","text":"To prepare your system to run the project follow those instructions:
Install the latest version of Python . Make sure to select the \"Add Python to PATH\" option during the installation process.
Open up a Terminal/Command Prompt (cmd)/Powershell window.
Check that Python was properly installed with this command (might need a terminal restart):
python --version\n
Install the latest version of git following this tutorial.
Check that git was properly installed with this command (might need a terminal restart):
git --version\n
(optional) Install the latest version of Visual Studio Code for GUI git management and Markdown preview.
"},{"location":"contribute/#working-locally","title":"Working locally","text":"In order to work locally:
Create a fork on GitHub. On your local PC navigate to a directory where you want to clone your forked repository and open a Terminal window inside. Clone the forked repository, using this command:
git clone https://github.com/user-name/forked-repository-name.git <DIR-PATH>\n
Instead of https://github.com/user-name/forked-repository-name.git
use your own link which can be found after clicking on the green <> Code
button and selecting the HTTPS
tab.
Replace the <DIR-PATH>
with a path to a directory or .
if you're inside the directory you want the project files to be cloned into.
This will automatically create a remote origin
repository pointing to your own fork.
Add the remote upstream
repository using this command:
git remote add upstream https://github.com/Gothic-Modding-Community/gmc.git\n
(optional) Create a Virtual Environment and activate it.
If you work on multiple Python projects, it might be worthwhile to create a Virtual Environment for each project to have separate library directories with installed modules/plugins.
python -m venv venv\n
This will create a venv
directory inside the current Terminal directory. Please keep that name as it's added to the .gitignore
project file.
Depending on the system, use one of these commands to activate the virtual environment.
Linux / macOSsource venv/bin/activate\n
Windows Powershellvenv\\Scripts\\activate.ps1\n
Windows Command Prompt (cmd)venv\\Scripts\\activate.bat\n
After activation there will be a (venv)
indicator near the Terminal prompt.
Don't close the Terminal
The virtual environment must be activated each time a new Terminal window is opened.
Install MkDocs with plugins using this command:
pip install -r requirements.txt\n
This will install all dependencies.
Fetch the git history from upstream
using this command:
git fetch upstream\n
Checkout a new local branch based on the upstream
dev
branch:
git checkout -b name-of-branch --track upstream/dev\n
An appropriate name for a branch is either a feature name or short description of what it changes - for example 3ds-articles
, fix-typos-for-contribution
. They do not have to be elaborate, up-to 4 words suffices.
Start a server with MkDocs using this command:
mkdocs serve\n
Visit the local site with this url http://127.0.0.1:8000/gmc/
. Any time you make change to any file, the website will rebuild itself and your browser will auto-refresh.
The server may be closed using the Control-C
shortcut while in the terminal/console.
When you are satisfied with a part of work, add and commit the files using these commands:
git add .\ngit commit -m \"add 3 articles about ZenGin\"\n
An appropriate commit message should be a sentence describing the changes.
When you are finished with the work, push the branch to origin
using this command:
git push origin name-of-branch\n
Create the pull request to the appropriate branch.
After pushing your local branch to the remote origin
, there will be a link available in the Terminal window. Use it to create the pull request using the pushed branch.
Another contribution:
Before contributing again, always use this command:
git fetch upstream \n
to make sure that you have an up-to-date upstream
git history. Follow then from step 8. git status\n
This command allows to check, if there are any changes in the project compared to the upstream
repository.
"},{"location":"contribute/#build-preferences","title":"Build preferences","text":"While working with the project, it's possible to set various environmental variables to configure it to your own preferences:
GMC_DEV_LOCALE
- is a 2-character language identifier (ex. en
, pl
), it sets the development language of the site. This will enforce that language to be the default and only built language. Helps to decrease build time and allows to easily change the language without modyfying the config file. Because of changes in the mkdocs-static-i18n
plugin, this is the only way to temporarily change the default language GMC_BUILD_ALTERNATES
- True
or False
value, activates the site build to also include alternate languages apart of the default language. Default behaviour is to omit alternates to decrease build time. GMC_ENABLE_ON_PUBLISH
- True
or False
value, activates all of the final build procedures, like adding of the last modified date, minifying of the resources etc. Environmental variables can be set temporarily for the currently open Terminal window:
Linuxexport GMC_DEV_LOCALE=en export GMC_BUILD_ALTERNATES=False; mkdocs serve\n
Windows Powershell$env:GMC_DEV_LOCALE=\"en\"\n$env:GMC_BUILD_ALTERNATES=\"False\"\nmkdocs serve\n
Windows Command Prompt (cmd)set GMC_DEV_LOCALE=en\nset GMC_BUILD_ALTERNATES=False\nmkdocs serve\n
"},{"location":"contribute/#build-performance","title":"Build performance","text":"To speed up the build process during development make sure that only 1 language is built, and consider using the --dirtyreload
option:
mkdocs serve --dirtyreload\n
This will cause only changed .md
files to rebuild. However, if you make changes to a template in the overrides
directory, no changes will be visible after the rebuild, because template modification requires a full rebuild.
"},{"location":"contribute/#submit-a-file","title":"Submit a file","text":"If working with git or Markdown is not viable or possible for you, you can submit files in a Google Docs format on the GMC Discord server and we will format and upload it to the page.
Only New English Content
This option is limited to new content in English. We can't deal with translations in this manner. For translations send a translated .md
file via a feedback channel, if you don't want to work directly with git, nor add the file via the GitHub interface.
"},{"location":"contribute/#translations","title":"Translations","text":"To provide multilingual support, our site uses the MkDocs i18n plugin.
"},{"location":"contribute/#add-new-language-support","title":"Add new language support","text":"To support a new language it needs to be added:
Indentation is important
You must preserve the correct amount of indentation, aka spacing between entries.
In the mkdocs.yml
configuration, in this example we're adding the xx
language:
plugins:\n - i18n:\n # ...\n languages:\n en:\n name: en - English\n build: true\n xx:\n name: xx - Language Name\n build: true\n
In the overrides/main.html
file to add the announcement text for untranslated content:
{%\n set announcement = {\n \"en\": \"This page has not yet been translated into LANGUAGE, therefore it is displayed in English.\",\n \"xx\": \"yyy\",\n }\n%}\n{%\n set call_to_action = {\n \"en\": \"Support us and translate!\",\n \"xx\": \"yyy\",\n }\n%}\n
Visit the official theme site. Make sure that the theme translation is complete there. If it's not, just follow their contribution guide and come back here, there is no need to wait for the changes in the theme.
"},{"location":"contribute/#add-translated-pages","title":"Add translated pages","text":"Each .md
file in the docs
directory can have a translated version. To add a translation for a given language create a copy with an added language suffix. For example index.md
will become index.xx.md
for the xx
language based on the settings in the mkdocs.yml
file.
Each untranslated article has the button in the upper right corner next to the title. It allows to quickly add the translation via the GitHub interface without the need for local file configuration.
"},{"location":"genome/","title":"Genome engine","text":""},{"location":"genome/#genome-engine","title":"Genome engine","text":"Genome engine is new engine by Piranha Bytes created for the game Gothic 3 and later used for the Risen and ELEX series of games.
"},{"location":"genome/general_info/object_persistence/","title":"Object persistence","text":""},{"location":"genome/general_info/object_persistence/#object-persistence","title":"Object persistence","text":"Please note the following warning about Risen 2, 3 and ELEX 1 and 2
The following information only applies to Gothic 3 (2006) and Risen (2009). While newer Genome engine games share the same overall concepts, they have significant implementation differences that warrant their own section.
The engine is, due to the nature of the games themselves, required to store and load a vast amount of different types of data from the user's hard-drive. In order to streamline this parsing and/or serialization process, Genome implements an object persistence system using its own built-in runtime type information (RTTI) system.
Any class derived from bCObjectBase
may declare its own member properties in such a way that when the object is then written into a file using the bCAccessorPropertyObject
class, its associated properties will be automatically serialized into the stream by using special preprocessor macros. When the object is read back from the file, the class will be automatically initialized using the stored members.
Additionally, classes may overload the Read
and Write
(OnRead
and OnWrite
in Risen 1) virtual methods that allow the class to save additional data required during parsing such as paths to other necessary files.
As this system is quite flexible, it is used to store most of the game's data, from meshes, animations and textures to level and quest data. This is quite different from ZenGin, as its object persistence system is only used for worlds, saves, output units and parts of compiled meshes.
"},{"location":"genome/general_info/object_persistence/#file-format","title":"File format","text":""},{"location":"genome/general_info/object_persistence/#files","title":"Files","text":"struct bCIOStream\n{\n char data[];\n};\n
struct eCArchiveFile\n{\n char8_t magic[8]; // \"GENOMFLE\"\n uint16_t version; // 0001\n uint32_t offset;\n\n char data[];\n\n uint32_t magic; // DEADBEEF\n uint8_t version; // 01\n uint32_t count;\n for( Count )\n {\n uint16_t length;\n char8_t string[length]; // (ASCII)\n }\n};\n
"},{"location":"genome/general_info/object_persistence/#bcaccessorpropertyobject","title":"bCAccessorPropertyObject","text":"bCAccessorPropertyObject::Read \n{\n uint16_t version; // 0x0001\n bool hasPropertyObject;\n if (hasPropertyObject)\n {\n bCPropertyObjectSingleton::ReadObject\n {\n uint16_t version; // 0x0001\n bool isPersistable; // 0x01 (GETrue)\n bCString className;\n bCPropertyObjectFactory::ReadObject\n {\n uint16_t version; // 0x0001\n bool isRoot; // 0x00 (GEFalse)\n uint16_t classVersion;\n bTPropertyObject<%,%>::Read\n {\n bCPropertyObjectBase::Read\n {\n uint16_t version; // 0x00C9 (201)\n }\n uint32_t size;\n }\n bTPropertyObject<%,%>::ReadData\n {\n bCPropertyObjectBase::ReadData\n {\n uint16_t version; // 0x00C9 (201)\n uint32_t count;\n for (count)\n {\n bCString name;\n bCString type;\n uint16_t version; // 0x001E (30)\n uint32_t size;\n uint8_t value[size];\n }\n }\n %::Read\n {\n // ClassName::OnRead/OnWrite()\n // uint16_t ClassVersion; ...\n }\n }\n }\n }\n }\n}\n
"},{"location":"genome/general_info/object_persistence/#ecprocessibleelement","title":"eCProcessibleElement","text":"Gothic 3Risen eCProcessibleElement::Load\n{\n uint32_t magic; // 0xD0DEFADE\n bCAccessorPropertyObject::Read\n {\n // Look above for bCAccessorPropertyObject definition\n }\n}\n
eCProcessibleElement::Load\n{\n bCAccessorPropertyObject::Read\n {\n // Look above for bCAccessorPropertyObject definition\n }\n}\n
"},{"location":"genome/general_info/object_persistence/#implementation","title":"Implementation","text":""},{"location":"genome/general_info/object_persistence/#a-practical-example","title":"A practical example","text":"Let's propose that we have a class which is declared like so:
class gCMyClass : public bCObjectRefBase\n{\npublic:\n\n gCMyClass() {}\n virtual ~gCMyClass() {}\n\n virtual bEResult Write(bCOStream&); // OnWrite for Risen\n virtual bEResult Read(bCIStream&); // OnRead for Risen\n\nprivate:\n\n DECLARE_PROPERTY(myInt, int);\n\n int someData;\n\n};\n
The hypothetical class then implements these virtual functions:
bEResult gCMyClass::Write(bCOStream& file)\n{\n file << someData;\n return bEResult_Ok;\n}\n\nbEResult gCMyClass::Read(bCIStream& file)\n{\n file >> someData;\n return bEResult_Ok;\n}\n
We then initialize the class in the following way:
gCMyClass object;\nobject.myInt = 1;\nobject.someData = 1;\n
If we now serialized, or to use the engine's term \"archived\", this instance into an ASCII stream, the result would look like this:
\n
"},{"location":"genome/tools/","title":"Tools","text":""},{"location":"genome/tools/#tools","title":"Tools","text":"Piranha Bytes did not release a modkit for their Genome engine, but the modding community has released a wide range of tools to work with the game's files and the engine itself.
Info
This page is under construction, for now, only handful of links are present.
"},{"location":"genome/tools/#gothic-3-sdk","title":"Gothic 3 SDK","text":"Georgeto, inspired by NicoDE's Risen SDK, has created an SDK for Gothic 3. It can be used to manipulate the engine in the similar way Union is able to manipulate ZenGin. GitHub repository
"},{"location":"zengin/","title":"ZenGin","text":""},{"location":"zengin/#zengin","title":"ZenGin","text":"The game engine ZenGin is used by Gothic 1 and 2. This section contains the documentation of the various aspects of ZenGin modding.
Script Reference
ZenGin uses its own scripting language called Daedalus. Check its functions, classes and extenders.
Scripts
Vob Classes
Virtual objects are objects which appear in the game world.
zCVob
Animations Section
Create new animations and put them into the game.
Animations
Union SDK
Learn how to create plugins with Union SDK, a community-made software development kit for ZenGin.
Getting Started
"},{"location":"zengin/music/","title":"Music","text":""},{"location":"zengin/music/#music","title":"Music","text":"Zengin uses DirectMusic for playing in-game soundtrack. To edit Gothic music files you need the Direct Music Producer, a program released by Microsoft and provided with older DirectX SDK.
Warning
Music files can't be packed in the .vdf
or .mod
archives, all music files must be located in /_work/Data/Music
directory.
"},{"location":"zengin/music/#file-formats","title":"File formats","text":"The music directory contains these file types:
.dls
- Downloadable Sound format file. This is the base for all other files. Contains:
Collections of virtual musical instruments. Wave files instruments use. .sty
- Style file. Contains:
Bands - settings for virtual instruments from .dls
. Patterns - fragments of tracks, that can be later merged, looped and superimposed on each other .sgt
- File with properly connected patterns - the final track
"},{"location":"zengin/music/#alternative-music-system","title":"Alternative Music System","text":"The zBassMusic plugin replaces Zengin's default music library with the much newer BASS library. This allows, among other things, to play music in such formats as .mp3
or .ogg
, and to pack songs into .vdf
and .mod
archives.
"},{"location":"zengin/video/","title":"Video","text":""},{"location":"zengin/video/#video","title":"Video","text":"To get a video cutscene, intro or outro into the game, the video needs to be in a proper format - BINK video format .bik
.
"},{"location":"zengin/video/#editing-the-video","title":"Editing the video","text":"The video you recorded and want to use has to be edited. My go-to editor for this is kdenlive. It works very well, it is free and open source, and it supports BINK video as an input, which is great if you want to include subtitles in the video.
My version of kdenlive does not know how to export video straight to .bik
so I just export my video to .mp4
and then convert it with RAD Video Tools.
"},{"location":"zengin/video/#rad-video-tools","title":"RAD Video Tools","text":"RAD Video Tools is a tool for converting other video formats to BINK .bik
that Gothic can use.
Warning
Gothic 1 bink implementation has some problems as you have to set the audio compression to 104 and above in RAD tools to get video to work in Gothic 1.
NicoDE's comment:
Add 100 to the audio compression level when encoding videos, e.g. 104 for level 4 with old sound format (should be mentioned in the RAD Video Tools documentation) for G1 without updated Miles libraries.
Note
Newest Union (1.0m at the time of writing) has a new patch for BINK video playback. The issue with sound should be fixed.
"},{"location":"zengin/anims/","title":"Animation","text":""},{"location":"zengin/anims/#animation","title":"Animation","text":""},{"location":"zengin/anims/#animations-in-zengin","title":"Animations in ZenGin","text":"Animations are (apart from maybe advanced programming work using Ikarus or Union) one of the most advanced modding techniques, since you not only must understand the way they work, but also know how to write the animation script and understand the whole scheme selection system, naming convention and of course know how to animate (that is my biggest problem :D). To get a new animation into ZenGin (the Gothic engine) is not difficult per se, I would describe it as tedious.
Luckily, there are tools to help us to achieve our goal - get a new animation to be used by the engine, and in effect, to be used and seen in the game.
To describe the whole process, I constructed this small tutorial, to help other people to get animations working and to spare them many hours of searching the excellent forum posts, that describe parts of the process. __
Excluding advanced programming work with Ikarus or Union, animations are arguably the most advanced modding discipline of ZenGin engine. Its difficulty stems for the fact that you not only have to understand the general concept, but also learn how to write the animation scripts and understand the whole scheme selection system, including naming conventions and, most important for last - actually know how to animate. Adding new animations into ZenGin is more tedious than actually difficult.
There are tool to help with this endeavor - to get a new animation implemented in the engine, and seeing its effects in game. Following tutorial has been constructed to help others to get their animations working without having to scour old forum posts for hours.
"},{"location":"zengin/anims/#prerequisites---tools--materials","title":"Prerequisites - Tools & Materials","text":" Gothic Mod Development Kit (MDK) Gothic 1 MDK - link Gothic 2 MDK - link Blender Kerrax's Import Export plugin - follow the installation instructions to install the plugin, make sure to set up the texture paths too Tool for decompiling animations GothicSourcer, or use phoenix or write your own using ZenLib "},{"location":"zengin/anims/#the-workflow","title":"The workflow","text":"This is the basic step-by-step workflow on how to get the animation into the game.
Load the actor (character or object) into your 3D software Create your animation Export the animation as an .asc
file Write the MDS file Run the game to compile your animations Test your animations in-game using a Daedalus script or a console command Sounds simple enough, except there is a lot missing. Even though the steps start with loading the actor into blender, understanding the system of animations to get high quality assets into your mod is more important.
"},{"location":"zengin/anims/#animation-types","title":"Animation \"types\"","text":"There are two main types of animations - skeletal
and morphmesh
animations. Character body animations are skeletal, and we animate the skeleton and the entire model (skin) moves around it. Morph mesh animation is, on the other hand, used for facial animations such as eating, blinking or talking and for animated meshes like wave water ferns or fish in Khorinis' harbor.
This guide focuses on skeletal animations. There are few different ones, all of which will have their own demonstration in the future. Categories are:
Standalone animation - waving, bowing, eating MOBSI animations - bed, alchemy table, anvil Item animations - sweeping the floor with a broomstick, using the horn, playing the lute Mandatory animations - running, walking, sneaking Combined/interpolated animations - picking stuff up, aiming with a bow/crossbow All of these animations are defined in an MDS file which will be talked about in the next sections.
"},{"location":"zengin/anims/events/","title":"None","text":"Acknowledgment
This tutorial was possible thanks to Kerrax, VAM and their excelent articles (MDS, EventTags) and Avallach from theModders who provided valuable insight.
"},{"location":"zengin/anims/events/#animation-event-block-overview","title":"Animation event block overview","text":"We often need to perform some other actions together with our animation, such as playing a sound effect, inserting item into NPC's hand or changing an item instance into a different one, like turning a raw steel into hot raw steel. These actions often need to be done at very specific moment during the animation playback, therefore they are defined using events(#aniamtion-events) in the event block which follows right after the animation definition. The event block is started and closed by curly brackets.
Example:
ani (\"s_RunL\" 1 \"s_RunL\" 0.0 0.1 M. \"Hum_RunLoop_M01.asc\" F 12 31) // animation\n{ // event block start\n\n *eventSFXGrnd (12 \"Run\") // animation event\n *eventSFXGrnd (24 \"Run\") // animation event\n ...\n *eventSFXGrnd (30 \"Run\") // animation event\n} // event block end\n
Warning
Each animation can define a maximum of 16 events. Should you need more, split the animation into parts and use next_ani
to chain them together.
"},{"location":"zengin/anims/events/#animation-events","title":"Animation events","text":"Animation events are commands telling engine to do something. Event *eventSFXGrnd(12 \"Run\")
will command the engine to play sound Run
at the very moment (12th frame) the character lands food on the ground. So with that in mind here is the general syntax as well as each animation event in the game.
General Syntax:
*EVENTNAME (FRAME KEYWORD \"INSTANCE\" [OPTIONAL] [A:VALUE] [B:VALUE])\n
FRAME
- all events specify on what frame int the animation source file .ASC
should this event happen
KEYWORD
- some events expect very specific keywords.
\"INSTANCE\"
- this indicates parameter is expected to be inside quotes, usually it;s slot/bone or item/sound instance name from the scrips
[OPTIONAL]
- this is an example of the optional parameter. Optional parameters will be indicated by brackets []
, if you don't specify them, the event will use the default value defined by the engine.
A:VALUE
- some events that have more than one optional parameter use a prefix to know which was specified
NODE_NAME
- will indicate any NODE
should work, be it bones (BIP01
...) or ZS_
slots (ZS_RIGHTHAND
)
SLOT
- this will indicate most likely only ZS_
slots will work.
Warning
Events should follow in ascending order by the frame they appear on. i. e. *eventTag(1 ...)
must come before *eventTag(2 ...)
Event Description eventCamTremor camera shake eventMMStartAni start morph-mesh eventPFX create particle effect eventPFXStop destroy particle effect eventSwapMesh exchange item meshes between two slots eventSFX create sound effect eventSFXGRND create sound effect on the ground eventTag generic event, does action specified in parameters Defined in engine but never used ? eventPFXGRND create particle effect on the ground eventSetMesh ? modelTag same as eventTag, but applies to morphmesh?"},{"location":"zengin/anims/events/#eventcamtremor","title":"eventCamTremor","text":"Earthquake effect (camera shake)
Example:
*eventCamTremor (12 1000 500 2 8 )\n
Syntax:
*eventCamTremor (FRAME RANGE DURATION MIN_AMPLIFIER MAX_AMPLIFIER)\n
eventCamTremor
- is a keyword, for camera shake event
Let's describe all the parameters
FRAME
- animation frame at which this event starts
RANGE
- range from which the effect will be 'felt' defined in in-game centimeters (1000 is 10 meters in-game)
DURATION
- duration of the effect in milliseconds
MIN_AMPLIFIER
- minimum amount of shaking in in-game centimeters
MAX_AMPLIFIER
- the maximum amount of shaking.
"},{"location":"zengin/anims/events/#eventmmstartani","title":"eventMMStartAni","text":"Start the animation of the morph-mesh that is attached to the specified node. Mostly used to start NPC facial animations or to animate bows/crossbows shooting.
Example:
*eventMMStartAni (14 \"T_HURT\")\n*eventMMStartAni (6 \"S_SHOOT\" \"ZS_RIGHTHAND\")\n*eventMMStartAni (6 \"S_BOOK_NEXT_PAGE\" \"ZS_RIGHTHAND\" I:0.5 H:5)\n
Syntax:
*eventMMStartAni (FRAME \"ANI_NAME\" [\"NODE_NAME\"] [I:INTENSITY] [H:HOLD_TIME])\n
FRAME
- animation frame at which animation should start
ANI_NAME
- name of the morph-mesh animation (specified in .MMS) file
NODE_NAME
- node in the hierarchy, to which morph mesh is attached. If not specified, a default value of BIP01 HEAD
will be used.
I:INTENSITY
- float value to specify blending of morph animation with the current one ?
H:HOLD_TIME
- time in seconds, how long will the animation \"stay\"
Both INTENSITY
and HOLD_TIME
can be specified in the MMS script. All gothic morph meshes specify those values in .MMS, therefore behavior when both specified in eventMMStartAni and .MMS file is unknown/untested
"},{"location":"zengin/anims/events/#eventpfx","title":"eventPfx","text":"Start particle effect at the specified bone.
Example:
*eventPFX (12 \"ZMODELLANDDUST\" \"Bip01\" )\n*eventPFX (2 1 \"DEMON_ATTACK\" \"BIP01 R HAND\" ATTACH)\n
Syntax:
*eventPFX (FRAME [PFX_HANDLE] \"PFX_NAME\" \"NODE_NAME\" [ATTACH])\n
FRAME
- animation frame at which particle effect starts
PFX_NAME
- name of the PFX instance
PFX_HANDLE
- an optional integer value. Specifying this creates a 'handle' and allows stop the PFX later using eventPFXStop
NODE_NAME
- node in the hierarchy. particle effect will be spawned at the node's position. If not specified, a default value of BIP01
will be used.
ATTACH
- keyword, including this keyword, will make particle effect follow the node specified, otherwise, it will stay where it spawned.
Tip
ATTACH
is used to create demons burning hand during the attack, while without this keyword dust particles are made to stay at the position where NPC landed after falling.
"},{"location":"zengin/anims/events/#eventpfxstop","title":"eventPFXStop","text":"Stops particle effect previously started by eventPfx
Example:
*eventPFX (2 1 \"DEMON_ATTACK\" \"BIP01 R HAND\" ATTACH) // starts pfx with handle 1\n...\n*eventPFXStop (70 1) // stops pfx started above\n
Syntax:
*eventPFXStop (FRAME PFX_HANDLE)\n
FRAME
- animation frame at which particle effect should disappear
PFX_HANDLE
- an integer value. Handle of the particle effect, that should be destroyed. Particle effect must be spawned using the same handle by eventPfx first
"},{"location":"zengin/anims/events/#eventswapmesh","title":"eventSwapMesh","text":"Move mesh from source NODE
to target node. Item should be present in the node already. Only mesh of the Items is moved, engine internally still keeps a reference to items in the original slot? Never used in game?
Example:
*eventSwapMesh (5 \"ZS_CROSSBOW\" \"ZS_LEFTARM\")\n
Syntax:
*eventSWAPMESH (FRAME \"SOURCE_NODE_NAME\" \"TARGET_NODE_NAME\")\n
FRAME
- animation frame at which transport of the mesh should happen
SOURCE_NODE_NAME
- source node containing the item.
TARGET_NODE_NAME
- target node that the item should be moved to.
Note
In some rare occasions duplicates item
"},{"location":"zengin/anims/events/#eventsfx","title":"eventSfx","text":"Play sound effect. It can be either SFX
instance from scripts, or .WAV
file.
Example:
*eventSFX (0 \"Drown\")\n*eventSFX (8 \"WHOOSH\" EMPTY_SLOT)\n*eventSFX (8 \"BAB_SIGH\" R:5000 EMPTY_SLOT) \n
Syntax:
*eventPFX (FRAME \"SFX_NAME\" [R:RANGE] [EMPTY_SLOT])\n
FRAME
- animation frame at which particle effect starts
SFX_NAME
- name of the SFX instance or .WAV
file
R:RANGE
- an optional integer value. The range from which the effect will be 'heard' defined in in-game centimeters (1000 is 10 meters in-game)
[EMPTY_SLOT]
- optional keyword. By default audio effects use a single audio channel (slot) per Model. That means every eventSFX
request will cancel any currently playing effect. If EMPTY_SLOT
is specified, audio will be played on the next available (empty) audio slot and other sounds will not be interrupted.
Note
A lot of original game animations contain EMTPY_SLOT
instead of EMPTY_SLOT
which was probably unintended. Gothic therefore acts as no keyword was provided, which causes a lot of sound interruptions. Therefore be mindful of spelling when copying original MDS scripts
"},{"location":"zengin/anims/events/#eventsfxgrnd","title":"eventSfxGrnd","text":"the same as eventSfx with only one difference, the sound effect name is appended with the current material name.
Example:
*eventSFXGrnd (12 \"Run\")\n
Syntax:
*eventSFXGrnd (FRAME \"SFX_NAME\" [R:RANGE] [EMPTY_SLOT])\n
Depending on the material of the texture, the character is standing on, the game will add one of the following suffixes:
Spacer Material Suffix Gothic 1 Gothic 2a UNDEF
_Undef \u2714\ufe0f \u2714\ufe0f EARTH
_Earth \u2714\ufe0f \u2714\ufe0f SAND
_Sand \u2714\ufe0f \u2714\ufe0f METAL
_Metal \u2714\ufe0f \u2714\ufe0f WATER
_Water \u2714\ufe0f \u2714\ufe0f WOOD
_Wood \u2714\ufe0f \u2714\ufe0f SNOW
_Snow \u274c \u2714\ufe0f STONE
_Stone \u2714\ufe0f \u2714\ufe0f default _Stone \u2714\ufe0f \u2714\ufe0f NPC running on grass texture, with material set to EARTH in world editor, will play sound Run_Earth
by using *eventSFXGrnd (12 \"Run\")
in run animation. _Earth
suffix is determined and added by the engine.
"},{"location":"zengin/anims/events/#eventtag","title":"eventTag","text":"This is a generic type of event that does different actions based on the first parameter after the frame parameter. It was probably later in development to extend MDS functionality without the need to expand parser itself. All parameters except FRAME
are passed inside quotes Further parameters are specific for every EVENT_TAG_TYPE
.
Waning
eventTag contrary to other events is validated only at runtime. If parameters are wrong, it won't work or might crash the game
Syntax:
*eventTag (FRAME \"EVENT_TAG_TYPE\" \"PARAMETER_1\" \"PARAMETER_2\" ... \"PARAMETER_N\")\n
FRAME
- Frame at which the event will execute. This parameter is always first and the same for all eventTags
EVENT_TAG_TYPE
- a type of event = action that should happen.
Here is a list of event tag types:
EVENT TAG TYPE Description DEF_CREATE_ITEM Creates item into slot DEF_INSERT_ITEM Inserts item to slot from inventory DEF_REMOVE_ITEM Removes item from slot to inventory DEF_DESTROY_ITEM Destroys item in slot DEF_PLACE_ITEM ~~Places item from slot into mob slot~~ Destroys item in slot DEF_EXCHANGE_ITEM Removes item in slot and replaces with new item DEF_FIGHTMODE Sets npc into weapon stance DEF_PLACE_MUNITION Inserts munition into slot DEF_REMOVE_MUNITION Remove munition back to inventory DEF_DRAWSOUND Plays weapon drawing sound based on weapon material DEF_UNDRAWSOUND Plays weapon sheating sound based on weapon material DEF_SWAPMESH Moves items visual to different slot visually DEF_DRAWTORCH Inserts torch DEF_INV_TORCH Moves torch to different slot temporarily DEF_DROP_TORCH Drops torch from slot to world DEF_HIT_LIMB Defines node which deals damage DEF_DIR Defines attack direction DEF_DAM_MULTIPLIER Defines damage mutliplier DEF_PAR_FRAME Defines frame range for blocking DEF_OPT_FRAME Defines damage frames DEF_HIT_END Defines last frame to continue combo DEF_WINDOW Defines frame for combo continuation"},{"location":"zengin/anims/events/#def_create_item","title":"DEF_CREATE_ITEM","text":"Creates a new item instance and inserts it into the specified slot. Item is not inserted permanently but only for the duration of interaction.
Example:
*eventTag (4 \"DEF_CREATE_ITEM\" \"ZS_RIGHTHAND\" \"ItMw_1H_Mace_L_04\")\n
Syntax:
*eventTag (FRAME \"DEF_CREATE_ITEM\" \"SLOT\" \"ITEM_INSTANCE\")\n
SLOT
- a name of the ZS_
slot, write in UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_insert_item","title":"DEF_INSERT_ITEM","text":"Insert the interaction item into the specified slot.
during mob interaction, inserted item instance is of instance taken from UseWithItem mob property. during item interaction (i.e. drink potion) item that started the SceneName will be inserted. In the example below: (1)
inserts ItMiSwordrawhot
that is defined in spacer into ZS_LEFTHAND
, then (2)
spawns ItMw_1H_Mace_L_04
(hammer) into ZS_RIGHTHAND
for anvil interaction.
Example:
ani (\"t_BSANVIL_S0_2_S1\" 1 \"s_BSANVIL_S1\" 0.0 0.0 M. \"Hum_BSAnvil_Jue00.asc\" F 4 9)\n{\n *eventTag (4 \"DEF_INSERT_ITEM\" \"ZS_LEFTHAND\") // (1)\n *eventTag (4 \"DEF_CREATE_ITEM\" \"ZS_RIGHTHAND\" \"ItMw_1H_Mace_L_04\") // (2)\n}\n
Syntax:
*eventTag (FRAME \"DEF_INSERT_ITEM\" \"SLOT\")\n
SLOT
- a name of the ZS_
slot, use UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
The well-known Gothic bug:
If player gets hit while drinking a potion, the effect of the potion is applied, but the potion remains in the inventory - the reason for the bug is that the potion item is inserted into hand using DEF_INSERT_ITEM
and would be removed from the world at the end of the drinking animation, while the potion's effect (a script function that increases stats) is applied at the very beginning of the animation. When the player is hit, the drinking animation is interrupted, and the engine does not remove the item from the world.
"},{"location":"zengin/anims/events/#def_remove_item","title":"DEF_REMOVE_ITEM","text":"Remove an item inserted into a slot via DEF_INSERT_ITEM
from the slot back into the inventory.
Example:
*eventTag (0 \"DEF_REMOVE_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_REMOVE_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_destroy_item","title":"DEF_DESTROY_ITEM","text":"Destroys an item inserted into a slot via DEF_INSERT_ITEM
. The item is removed from the world.
Example:
*eventTag (0 \"DEF_DESTROY_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_DESTROY_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_place_item","title":"DEF_PLACE_ITEM","text":"Remove the item inserted via eventTag DEF_INSERT_ITEM
from the slot and the world. In terms of its action, eventTag DEF_PLACE_ITEM
is a synonym for DEF_DESTROY_ITEM
. Possibly fixed by SystemPack. See intended use.
Example:
*eventTag (0 \"DEF_PLACE_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_PLACE_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
Intended use Presumably, the eventTag DEF_PLACE_ITEM
was intended to have different behavior: If an NPC interacts with a MOB that has a ZS_SLOT
node, then move the item inserted via DEF_INSERT_ITEM
from the NPC node into the ZS_SLOT
node on the MOB. An example would be orc priest hearts in the Temple of the Sleeper, Gothic 1.
// Sleeper Portal\nani (\"t_SPORTAL_Stand_2_S0\" 1 \"s_SPORTAL_S0\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 0 19)\nani (\"s_SPORTAL_S0\" 1 \"s_SPORTAL_S0\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 20 20)\nani (\"t_SPORTAL_S0_2_Stand\" 1 \"\" 0.0 0.2 M. \"Hum_SleeperPortal_M01.asc\" R 0 19)\nani (\"t_SPORTAL_S0_2_S1\" 1 \"s_SPORTAL_S1\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 21 90 FPS:10)\n{\n *eventTag (60 \"DEF_INSERT_ITEM\" \"ZS_RIGHTHAND\") // (1)\n *eventTag (90 \"DEF_PLACE_ITEM\") // (2)\n}\nani (\"s_SPORTAL_S1\" 1 \"s_SPORTAL_S1\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 91 91)\nani (\"t_SPORTAL_S1_2_Stand\" 1 \"\" 0.0 0.2 M. \"Hum_SleeperPortal_M01.asc\" F 90 100)\n
During animation on 60th frame,(1)
inserts orc priest sword from the inventory, and (2)
on 90th frame, presumably, should have left the sword inserted into the heart sticking out. There is ZS_SLOT
present to indicate the location of the sword after insertion into the heart.
In reality, (2)
simply removes the sword from the world like DEF_DESTROY_ITEM
. This was most likely an unrealized idea. In G2, eventTag DEF_PLACE_ITEM
is not used.
"},{"location":"zengin/anims/events/#def_exchange_item","title":"DEF_EXCHANGE_ITEM","text":"Replace an item in a slot with another item. Item present in the slot is removed from the slot and the world, new item specified in parameters is created and inserted in the same slot.
Example:
*eventTag (37 \"DEF_EXCHANGE_ITEM\" \"ZS_LEFTHAND\" \"ItMiSwordrawhot\")\n
Syntax:
*eventTag (FRAME \"DEF_EXCHANGE_ITEM\" \"SLOT\" \"ITEM_INSTANCE\")\n
SLOT
- a name of the ZS_
slot, use UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_fightmode","title":"DEF_FIGHTMODE","text":"Set fight mode for the model. Used in transition animations to weapon stances like t_1h_2_1hRun
.
Example:
*eventTag (5 \"DEF_FIGHTMODE\" \"FIST\")\n
Syntax:
*eventTag (FRAME \"DEF_FIGHTMODE\" \"FIGHT_MODE\")\n
FIGHT_MODE
- fight modes are defined in the engine and can be one of the following:
\"\"
- remove weapon \"FIST\"
- fists \"1H\"
or \"1HS\"
- one-handed weapon \"2H\"
or \"2HS\"
- two-handed weapon \"BOW\"
- bow \"CBOW\"
- crossbow \"MAG\"
- magic Example: Parameter 1H
sets fight mode for the actor (in the engine), but also exchanges sword from ZS_SWORD
slot to the ZS_RIGHTHAND
"},{"location":"zengin/anims/events/#def_place_munition","title":"DEF_PLACE_MUNITION","text":"Place ammunition, from inventory such as an arrow into the specified slot. Used in reloading animations after a bow/crossbow shot.
Example:
*eventTag (9 \"DEF_PLACE_MUNITION\" \"ZS_RIGHTHAND\")\n
Syntax:
*eventTag (FRAME \"DEF_PLACE_MUNITION\" \"SLOT\")\n
SLOT
- slot where the ammunition is created. There are only two valid slot names: \"ZS_LEFTHAND\"
and \"ZS_RIGHTHAND\"
.
Ammunition always corresponds to the equipped ranged weapon instance and its munition
field in the C_ITEM
instance
instance ItRw_Sld_Bow(C_Item)\n{\n name = \"\u041b\u0443\u043a\";\n mainflag = ITEM_KAT_FF;\n flags = ITEM_BOW;\n material = MAT_WOOD;\n value = Value_SldBogen;\n damageTotal = Damage_SldBogen;\n damagetype = DAM_POINT;\n munition = ItRw_Arrow;\n cond_atr[2] = ATR_DEXTERITY;\n cond_value[2] = Condition_SldBogen;\n visual = \"ItRw_Sld_Bow.mms\";\n description = name;\n text[2] = NAME_Damage;\n count[2] = damageTotal;\n text[3] = NAME_Dex_needed;\n count[3] = cond_value[2];\n text[5] = NAME_Value;\n count[5] = value;\n};\n
"},{"location":"zengin/anims/events/#def_remove_munition","title":"DEF_REMOVE_MUNITION","text":"Remove ammunition previously placed by DEF_PLACE_MUNITION event
Example:
*eventTag (19 \"DEF_REMOVE_MUNITION\")\n
Syntax:
*eventTag (FRAME \"DEF_REMOVE_MUNITION\")\n
"},{"location":"zengin/anims/events/#def_drawsound","title":"DEF_DRAWSOUND","text":"Play weapon drawing sound. Determined by drawn weapon material
field in the C_ITEM
instance
\u201cDrawSound_WO.wav\u201d
- for MAT_WOOD; \"DrawSound_ME.wav\"
- for MAT_METAL. Example:
*eventTag (19 \"DEF_DRAWSOUND\")\n
Syntax:
*eventTag (FRAME \"DEF_DRAWSOUND\")\n
"},{"location":"zengin/anims/events/#def_undrawsound","title":"DEF_UNDRAWSOUND","text":"Play weapon sheathing sound. Determined by drawn weapon material
field in the C_ITEM
instance
\"UndrawSound_WO.wav\u201d
- for MAT_WOOD; \"UndrawSound_ME.wav\"
- for MAT_METAL. Example:
*eventTag (19 \"DEF_UNDRAWSOUND\")\n
Syntax:
*eventTag (FRAME \"DEF_UNDRAWSOUND\")\n
"},{"location":"zengin/anims/events/#def_swapmesh","title":"DEF_SWAPMESH","text":"Swap items in the specified slots.
Example:
*eventTag (5 \"DEF_SWAPMESH\" \"ZS_CROSSBOW\" \"ZS_LEFTHAND\")\n
Syntax:
*eventTag (FRAME \"DEF_SWAPMESH\" \"SLOT1\" \"SLOT2\")\n
SLOT1
- name of the slot with item to be exchanged.
SLOT2
- name of the slot with item to be exchanged.
Warning
In case SLOT1
or SLOT2
is equal to \"ZS_LEFTHAND\"
or \"ZS_RIGHTHAND\"
, the engine will attempt to put the model into fight mode similar to DEF_FIGHTMODE event. This can lead to game freezing.
Tip
This event is similar to the *eventSwapMesh. The main difference is *eventSwapMesh will swap only visuals (meshes) of the items, while eventTag DEF_SWAPMESH will swap items and their slot references. After a game reload, meshes would reset their positions if swapped using *eventSwapMesh. Additionally *eventSwapMesh does not try to set the model into fight mode.
"},{"location":"zengin/anims/events/#def_drawtorch","title":"DEF_DRAWTORCH","text":"Does nothing? never used.
Example:
*eventTag (5 \"DEF_DRAWTORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_DRAWTORCH\")\n
"},{"location":"zengin/anims/events/#def_inv_torch","title":"DEF_INV_TORCH","text":"Temporarily return torch into inventory, for the duration of mob/item interaction. Does nothing if a torch is not present in ZS_LEFTHAND
. Used before interacting with mobs like bed, or before performing eating animations that require a left hand.
Example:
*eventTag (5 \"DEF_INV_TORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_INV_TORCH\")\n
"},{"location":"zengin/anims/events/#def_drop_torch","title":"DEF_DROP_TORCH","text":"Drop the torch onto the ground if present in ZS_LEFTHAND
.
Example:
*eventTag (5 \"DEF_DROP_TORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_DROP_TORCH\")\n
"},{"location":"zengin/anims/events/#def_hit_limb","title":"DEF_HIT_LIMB","text":"Set which node is dealing damage to others. This node is then used in calculations for collisions. Up to four slots can be specified.
Example:
// humans - fist attacks\n*eventTag (0 \"DEF_HIT_LIMB\" \"BIP01 R HAND\")\n// humans - sword attacks\n*eventTag (0 \"DEF_HIT_LIMB\" \"ZS_RIGHTHAND\")\n// animals \neventTag (0 \"DEF_HIT_LIMB\" \"BIP01 HEAD\")\n
Syntax:
*eventTag (FRAME \"DEF_HIT_LIMB\" \"SLOT1\" \"SLOT2\" \"SLOT3\" \"SLOT4\")\n
"},{"location":"zengin/anims/events/#def_dir","title":"DEF_DIR","text":"Set the direction of the attack. Enemy block animation is determined by this information. Not used.
Example:
*eventTag (0 \"DEF_DIR\" \"O\")\n*eventTag (0 \"DEF_DIR\" \"L\")\n*eventTag (0 \"DEF_DIR\" \"OUOL\") // combo attack - top, under, \n
Syntax:
*eventTag (FRAME \"DEF_DIR\" \"DIRECTIONS\")\n
DIRECTIONS
- can be up to 10 characters, each character defines one attack direction during combo attack, default is O
- capital letter O
, not zero 0
. Possible values are
If the enemy is trying to block an attack with a defined direction it will choose a matching animation adding a direction suffix like t_1hParade_U
for opponent's attack direction U
Note
Sadly this feature was unused in Gothic 1. All attacks use O
direction and only defined animations for blocking are for said t_1hParade_O
But can be easily restored with a few new animations and MDS file edits. In Gothic 2, blocking animation uses zero 0
instead of O
which might indicate the feature no longer works.
"},{"location":"zengin/anims/events/#def_dam_multiplier","title":"DEF_DAM_MULTIPLIER","text":"Set damage multiplier. For the attack animation. The damage will be multiplied by a provided number regardless of whether the attack is a critical attack or not.
Example:
*eventTag (0 \"DEF_DAM_MULTIPLIER\" \"0.2\")\n*eventTag (0 \"DEF_DAM_MULTIPLIER\" \"2.0\")\n
Syntax:
*eventTag (FRAME \"DEF_DAM_MULTIPLIER\" \"MULTIPLIER\")\n
MULTIPLIER
- float value inside quotes
"},{"location":"zengin/anims/events/#def_par_frame","title":"DEF_PAR_FRAME","text":"Set frame range during which damage is blocked. If not provided whole animation is blocking damage.
Example:
*eventTag (0 \"DEF_PAR_FRAME\" \"1 8\")\n
Syntax:
*eventTag (FRAME \"DEF_PAR_FRAME\" \"START_FRAME_END_FRAME\")\n
START_FRAME_END_FRAME
- Two integer numbers inside quotes. if \"0 0\"
is provided, the animation will be blocking it's whole duration
"},{"location":"zengin/anims/events/#def_opt_frame","title":"DEF_OPT_FRAME","text":"Set frames during which damage collisions should be evaluated. Damage is checked for collision with \"hit limb\". This event usually comes in pair with eventTags DEF_WINDOW and DEF_HIT_END
Example:
*eventTag (0 \"DEF_OPT_FRAME\" \"6\") // on hit attack, hit on 6th frame\n*eventTag (0 \"DEF_OPT_FRAME\" \"6 30\") // 2 attack combo, hit at 6th and 30th frame\n
Syntax:
*eventTag (FRAME \"DEF_OPT_FRAME\" \"HIT_FRAME1 HIT_FRAME2 ... HIT_FRAME10\")\n
HIT_FRAME1 HIT_FRAME2 ... HIT_FRAME10
- specify 1 and up to 10 integers separated by space inside quotes. Each number represents frame at which damage should be done. Number of provided hit frames determines number of combos (max 10 possible).
"},{"location":"zengin/anims/events/#def_hit_end","title":"DEF_HIT_END","text":"Set frames at which the combo is \u201ccut off\u201d if you do not press the \u201cup\u201d key (G1) or the left mouse button (G2) during the attack. Gothic has bug that in this case we will hear all the sound effects following this frame, and the animation ends with the character\u2019s characteristic twitching. The number of frames specified in this entry must match the number of frames of the eventTag DEF_OPT_FRAME.
Example:
*eventTag (0 \"DEF_HIT_END\" \"32\") \n*eventTag (0 \"DEF_HIT_END\" \"27 48 75\") \n
Syntax:
*eventTag (FRAME \"DEF_HIT_END\" \"HIT_END1 HIT_END2 ... HIT_END10\")\n
HIT_END1 HIT_END2 ... HIT_END10
- specify 1 and up to 10 integers separated by space inside quotes. After this frame combo cannot be continued and model will continue animation until the current DEF_WINDOW -
1`. Which is usually animation returning to idle stance
"},{"location":"zengin/anims/events/#def_window","title":"DEF_WINDOW","text":"Set a \u201cwindow\u201d in the animation - an interval of frames during which you need to press the \u201cup\u201d (G1) or the left mouse button (G2) to continue the combo strike.
Example:
*eventTag (0 \"DEF_WINDOW\" \"9 19\") // one combo with window from 9-19 (can be chained)\n*eventTag (0 \"DEF_WINDOW\" \"10 23 32 41 58 70\") // 3 combos with windows 10-23 then 32-41, 58-70\n
Syntax:
*eventTag (FRAME \"DEF_WINDOW\" \"HIT_1_WINDOW_START HIT_1_WINDOW_END HIT_2_WINDOW_START HIT_2_WINDOW_END ...\")\n
HIT_1_WINDOW_START HIT_1_WINDOW_END HIT_2_WINDOW_START HIT_2_WINDOW_END
- specify 1 and up to 20? integers separated by space inside quotes. A window consists of a start and end frame, therefore for each DEF_OPT_FRAME, you must provide 2 numbers.
HIT_WINDOW_START
- First value of the pair defines frame from which attack can continue. HIT_WINDOW_END
- Second value is a little confusing. It defines START of the next attack animation. Ability to continue combo stops at DEF_HIT_END frames. Usually there are few frames of animation, where characters returns to idle position. HIT_WINDOW_END
should be one frame after characters return to idle stance, which should also be first frame of the next attack "},{"location":"zengin/anims/events/#attack-eventtags-explained","title":"Attack eventTags explained","text":"This is original attack combo from Gothic 1
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n *eventTag (0 \"DEF_HIT_LIMB\" \"ZS_RIGHTHAND\")\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 36 73 107\") \n *eventTag (0 \"DEF_HIT_END\" \"31 63 95 113\")\n *eventTag (0 \"DEF_WINDOW\" \"10 33 42 65 78 97 110 113\")\n *eventSFX (4 \"Whoosh\" EMPTY_SLOT )\n *eventSFX (72 \"BACK\" EMPTY_SLOT )\n}\n
I will edit it slightly to make it more readable. Let's focus on the DEF_OPT_FRAME, DEF_HIT_END,
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n ...\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 36 73 107 \") \n *eventTag (0 \"DEF_HIT_END\" \" 31 63 95 113\")\n *eventTag (0 \"DEF_WINDOW\" \" 10 33 42 65 78 97 110 113\")\n ...\n}\n
Let's focus only on the first combo.
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n ...\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 ...\") \n *eventTag (0 \"DEF_HIT_END\" \" 31 ...\")\n *eventTag (0 \"DEF_WINDOW\" \" 10 33 ...\")\n ...\n}\n
Frames Animation Description 1 animation start 1..4 swing of the sword 4 sword is in the front of the model DEF_OPT_FRAME
- test damage collisions at this frame 4..10 end of the sword swing 10 model stands ready to start next swing DEF_WINDOW
- user can press key to advance combo from this frame. 10..31 slight idle 'shake' if player continues combo, animation playback will jump to the frame 33 (DEF_WINDOW
second pair), from the animation perspective, next attack starts from pose similar to frame 10. If perfect inputs would be provided, animation would continue perfectly. 31 DEF_HIT_END
- ends user input. 31..32 model returns to the idle position 32 idle position, standing with sword in hand animation will end here, if combo not continued (DEF_WINDOW
second pair - 1) 33 first frame of the next attack (similar to frame 10) DEF_WINDOW
second pair, start of next attack"},{"location":"zengin/anims/events/#eventpfxgrnd","title":"eventPfxGrnd","text":"Not used anywhere in the original game. Could possibly spawn particle effect like eventPfx but with an added suffix similar to how eventSfxGrnd works. Needs to be investigated.
Syntax:
*eventPFXGRND (FRAME)\n
"},{"location":"zengin/anims/events/#eventsetmesh","title":"eventSetMesh","text":"Unknown
Syntax:
*eventSETMESH (FRAME \"NODE_NAME\")\n
"},{"location":"zengin/anims/events/#modeltag","title":"modelTag","text":"Should work similarly to eventTag, but can be defined inside aniEnum block and applies to all animations of the Model.
Syntax:
*modelTag (FRAME \"EVENT_TAG_TYPE\" \"PARAMETER1\" \"PARAMETER2\" \"PARAMETER3\" \"PARAMETER4\" ... )\n
"},{"location":"zengin/anims/mds/","title":"MDS - model animation script","text":""},{"location":"zengin/anims/mds/#mds---model-animation-script","title":"MDS - model animation script","text":"Tip
The MDS syntax is very simple and scripts can be edited in any text editor. It is, however, easier to work in an editor with a proper syntax highlighting. Daedalus Language Server's dev branch already merged the MDS grammar for syntax highlighting, we can expect it in the next release.
Model animation script is a file describing what skeleton should be used, what body meshes work with this set of animations and how should the animations be named, how fast they run, what animation is supposed to start after the current one is finished and much more. These files are located in Gothic\\_work\\DATA\\Anims\\
directory.
Whilst the code seems long and terrifying, it is in fact rather simple, and this guide will try to explain it whole.
Don't forget to use the search
If you search this file for t_Yes
, you will get an example of the first type of animation - \"standalone\"
To play the animation in game you use this console command play ani t_yes
.
"},{"location":"zengin/anims/mds/#syntax-and-keywords","title":"Syntax and keywords","text":"Let us get a quick look at the naming convention to get a basic idea what is going on before we start.
The first letter indicates a type of animation (transition - t_
- or state - s_
). Then depending on the animation type we have:
Transition animation
t_Run_2_Sneak\n
Transition animation from the run animation to the sneak animation. t_BSANVIL_Stand_2_S0\n
Transition animation for the blacksmith's anvil from standing to state 0. State animation
s_Run\n
State animation for the looping animation. s_BSANVIL_S0\n
State animation for the blacksmith's anvil and its first state."},{"location":"zengin/anims/mds/#ani","title":"ani","text":"This is the main command you will be using while defining new animations.
Example:
ani (\"t_Yes\" 2 \"\" 0.1 0.1 M. \"Hum_Yes_M01.asc\" F 1 44)\n
Syntax: ani (ANI_NAME LAYER NEXT_ANI BLEND_IN BLEND_OUT FLAGS ASC_NAME ANI_DIR START_FRAME END_FRAME)\n
ani
- is a keyword, we are defining new animation Let's describe all the parameters
ANI_NAME
- animation name, we use it in Daedalus as animation identifier
There is a naming convention, that is recommended and sometimes required to be used.
prefix t_
- transition animations prefix s_
- state animations - they usually run in a loop prefix c_
- animations used for animation combining/interpolation LAYER
- layer number for multi-layer animations
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
If we set it to 0.5, it takes 0.5 seconds for this animation to take full effect. At 0.0 s the previous animation has full effect on the bones of the skeleton, at 0.1 s it is influenced by 20% by this animation and at 0.5s it is completely influenced by this animation and the previous one has no effect.
BLEND_OUT
- time in seconds describing animation blending at the end
FLAGS
- flags, that describe animation behavior
M - specifies a movement animation, the animation of the model translates into a changed position in the game world R - the same as M but for rotation E - this flag makes this animation run only, if the animation in the same layer are finished, this is used in the movement animations. The animation s_walk
(walking loop animation) runs, when the player is walking,when he stops the transition animation to standing state is played t_walk_2_stand
. This animation uses the E flag to wait for the walk cycle animation to finish, to smoothly transition into the standing state. F - the engine ignores height coordinate - doesn't keep the model \"glued\" to the ground (falling/flying animation) I - specifies idle animation - breathing, standing with a drawn weapon and moving the weapon ASC_NAME
- name of the source file exported from Blender
ANI_DIR
- direction of the animation
START_FRAME
- on what frame from the source file the animation starts
END_FRAME
- on what frame from the source file the animation ends
"},{"location":"zengin/anims/mds/#anialias","title":"aniAlias","text":"Generally considered as one of the most useful commands, aniAlias
is used to create an alias (hard link for UNIX users) for an already defined animation.
Example:
aniAlias (\"t_Sneak_2_Run\" 1 \"s_Run\" 0.0 0.1 M. \"t_Run_2_Sneak\" R)\n
Syntax: aniAlias (ANI_NAME LAYER NEXT_ANI BLEND_IN BLEND_OUT FLAGS ALIAS_NAME ANI_DIR)\n
ANI_NAME
- name of the new animation
LAYER
- layer the animation is on
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
BLEND_OUT
- time in seconds describing animation blending at the end
FLAGS
- flags, that describe animation behavior
ALIAS_NAME
- name of the animation we want to use as a source for the alias
ANI_DIR
- direction of the animation
If we look for the animation in the example we can see that there is a related one just one line above
ani (\"t_Run_2_Sneak\" 1 \"s_Sneak\" 0.1 0.0 M. \"Hum_Sneak_M01.asc\" F 0 10)\naniAlias (\"t_Sneak_2_Run\" 1 \"s_Run\" 0.0 0.1 M. \"t_Run_2_Sneak\" R)\n
In this example we are defining t_Sneak_2_Run
animation and we are specifying that the animation after this one is finished will be s_Run
and that it is being made by reversing animation t_Run_2_Sneak
by specifying the R
flag."},{"location":"zengin/anims/mds/#aniblend","title":"aniBlend","text":"AniBlend is used to define animations that are a result of blending of two animations. This animation is not animated by hand, but it is dynamically generated by the engine during run-time.
Example
aniBlend (\"t_RunR_2_Run\" \"s_Run\" 0.2 0.2)\n
Syntax: aniBlend (ANI_NAME NEXT_ANI BLEND_IN BLEND_OUT)\n
ANI_NAME
- name of the new animation
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
BLEND_OUT
- time in seconds describing animation blending at the end
"},{"location":"zengin/anims/mds/#anisync","title":"aniSync","text":"Not used in the game.
"},{"location":"zengin/anims/mds/#anibatch","title":"aniBatch","text":"Not used in the game.
"},{"location":"zengin/anims/mds/#animation-state-machine","title":"Animation state machine","text":"More complex animations such as MOBSI animations form a state machine - an animation set.
MDS script for the big chestModel (\"CHESTBIG_OCCRATELARGE\")\n{\n meshAndTree (\"CHESTBIG_OCCRATELARGE.asc\")\n\n aniEnum\n {\n// Closed chest\n ani (\"s_S0\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 20 20)\n// Opening the chest \n ani (\"t_S0_2_S1\" 1 \"s_S1\" 0.0 0.0 M. \"CHESTBIG_USE.ASC\" F 50 79)\n {\n *eventSFX (50 \"chest_try\")\n *eventSFX (55 \"chest_open\")\n }\n// Opened chest\n ani (\"s_S1\" 1 \"s_S1\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 80 80)\n// Closing the chest\n ani (\"t_S1_2_S0\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" R 50 79)\n {\n *eventSFX (78 \"chest_close\")\n }\n// Pick lock broken\n ani (\"t_S0_Try\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 96 124)\n {\n *eventSFX (100 \"chest_try\")\n *eventSFX (115 \"Hammer\")\n }\n }\n}\n
stateDiagram-v2\n s_S0 : Closed chest\n t_S0_2_S1 : Opening the chest\n s_S1 : Opened chest\n t_S1_2_S0 : Closing the chest\n t_S0_Try : Pick lock broken\n [*] --> s_S0\n s_S0 --> s_S0\n\n s_S0 --> t_S0_2_S1\n t_S0_2_S1 --> s_S1\n s_S1 --> s_S1\n\n s_S1 --> t_S1_2_S0\n t_S1_2_S0 --> s_S0\n\n s_S0 --> t_S0_Try\n t_S0_Try --> s_S0
"},{"location":"zengin/anims/tutorials/standalone_animation/","title":"Standalone animation","text":""},{"location":"zengin/anims/tutorials/standalone_animation/#standalone-animation","title":"Standalone animation","text":"Acknowledgment
This tutorial would not be possible without the ZenGin documentation available in the mod-kit. Further credits also go to Mark56 who helped me understand animations in the first place, Fawkes and his request for me to do some animations for his excellent mod - Replay Mod, and last but not least Flosha from the Phoenix team who was the one for whom I offered to write this tutorial to help with the development of the Phoenix project.
Let us start with the easiest animation - a very simple gesturing animation.
Info
You can find some of the videos that are mentioned in the text below in this play-list.
Firstly we have to have the animation source files ready. Best way to decompile them is using Gothic Sourcer. In GothicSourcer you choose Tools > Decompiler models > Dynamic (MDS or MSB) and choose an MDS file of your choice - Humans.mds
in our case and then click the decompile button.
"},{"location":"zengin/anims/tutorials/standalone_animation/#animating","title":"Animating","text":"Open Blender, File > Import > Kerrax ASCII model (.asc), navigate to the folder with your decompiled animation files and select HUM_BODY_NAKED0.ASC
. This file contains the skeleton and skin model for human NPCs.
What bone hierarchy is this model using?
If you open the .mds
file, you can see a command meshAndTree
that specifies what model contains the skeleton. And there lies our answer:
Model (\"HuS\")\n{\n meshAndTree (\"Hum_Body_Naked0.ASC\" DONT_USE_MESH)\n
A windows pops up and you can read some interesting information about the model you are about to import. We are interested in the fact that Completely replace current scene is ticked, we want to use Armature modifier, and we also want to Try to connect bones and Use sample meshes from folder. You should provide a path to a directory with the sample meshes - these are meshes for items, that usually go into slot bones. Lastly, the space transformation scale should be set to 0.01. This is because ZenGin works with centimeter units and one unit in Blender is a meter.
Click import and wait for the magic to happen.
This video shows a freshly imported model with all default meshes.
Note
If we now want to play (or edit) existing animation, we can now load it on top of this. Just as before File > Import > Kerrax ASCII model (.asc) and select different animation file (or armor file), for example Hum_SmokeHerb_Layer_M01.asc
for an animation file.
Gothic characters are modular and you can change their heads on the fly, even during gameplay as seen in this amazing video from my dear friend and colleague Fawkes - Head changing. Let's add a head so that we can see how the whole body will behave while we are animating. File > Import > Kerrax ASCII model (.asc), navigate to your head model. You will have to decompile it like we did with the body itself. We will import HUM_HEAD_PONY.ASC
. Please make sure to select the target bone for importing Bip01 Head, this will attach the head to the proper bone, just like the engine does it.
Now we have everything ready to start animating. The video shows the DopeSheet a nice way to edit keyframes.
DopeSheet
Blender's dope sheet can be used to copy entire sets of keyframes. It is useful if we want to create a looping animation.
We can import an animation into Blender as a base.
Tip
If you don't know the name of the animation, just go into the game and make your character perform the animation you want. While in MARVIN mode, you can press G
and the animation information together with other info will be displayed right on the screen
In this video we can see that the idle standing animation is s_run
. We want to make an animation that is going to start from this idle animation, so we will import it into blender. We find it by looking into the .mds
file, look for s_run
name and get the name of the file.
ani (\"s_Run\" 1 \"s_Run\" 0.1 0.1 MI \"Hum_RunAmbient_M01.asc\" F 1 50) \n
As we can see, we have to import the Hum_RunAmbient_M01.asc
file. Next goes the first trick. Since we want our animation to end exactly, as it started - ether because we want the hero to continue his standing animation, or we want to make a looping animation, we somehow have to copy the pose. We use the DopeSheet screen, to delete all keyframes and then copy the keyframe set from keyframe number 0 and drag it somewhere to the end of the timeline.
Once the animation is done, we have to export it into an asc
format again, File > Export > Kerrax ASCII model (.asc) and then save it to _work\\data\\Anims\\asc\\
so the engine can see it and convert it. There are many options here that we will explore later, but we have tick Export animation and pick bones that we want to export - this is useful for animations that are played on different layers (dialogue gestures, scratching head, scratching a shoulder,...).
"},{"location":"zengin/anims/tutorials/standalone_animation/#animation-script","title":"Animation script","text":"Now that we have exported the animation, we now have to define it in Humans.mds
.
Open the file, scroll to the end and define a new animation.
Attention
All ani
code has to be between the curly brackets, this means you have to insert it before the last two closing curly brackets } }
.
Example:
ani (\"t_backpain\" 1 \"\" 0.0 0.0 M. \"Hum_back.ASC\" F 0 121) \n
Save the Humans.mds
file and try it in game. Nothing happens! The reason is that the mds
has been already compiled, and we have to recompile it. The easiest is to go to Anims\\_compiled
and delete HUMANS.MSB
. Run the game and try to play the animation again (play ani t_backpain
in MARVIN console) and now everything should work.
Amazing, now you have your first animation in the game. And you can use it to do some fun stuff, like in dialogues using the AI_PlayAni
function.
"},{"location":"zengin/anims/tutorials/standalone_animation/#example-dialogue","title":"Example dialogue","text":"instance DIA_Xardas_Back (C_INFO)\n{\n npc = NONE_100_Xardas;\n nr = 11;\n condition = DIA_Xardas_Back_Condition;\n information = DIA_Xardas_Back_Info;\n permanent = TRUE;\n description = \"What's wrong?\";\n};\n\nfunc int DIA_Xardas_Back_Condition () {\n return TRUE;\n};\n\nfunc void DIA_Xardas_Back_Info () {\n AI_Output (self, hero, \"DIA_Xardas_MOB_14_00\"); // My back hurts so much.\n\n // This is our animation!!!!!\n AI_PlayAni(self, \"T_BACKPAIN\"); \n AI_Output (self, hero, \"DIA_Xardas_MOB_14_01\"); // How do YOU feel?\n\n AI_Output (hero, self, \"DIA_Xardas_MOB_14_02\"); // My back is fine.\n AI_StopProcessInfos(self);\n};\n
"},{"location":"zengin/general_info/directory_structure/","title":"ZenGin directory structure","text":""},{"location":"zengin/general_info/directory_structure/#zengin-directory-structure","title":"ZenGin directory structure","text":"Modding is all about changing the game files. To achieve that, we have to know the directory (folder) structure of a Gothic game.
\u251c\u2500\u2500 Data\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 $Templates$\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 modvdf\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 Plugins\n\u251c\u2500\u2500 Miles\n\u251c\u2500\u2500 Saves\n\u251c\u2500\u2500 System\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 Autorun\n\u2514\u2500\u2500 _work\n \u2514\u2500\u2500 DATA\n \u251c\u2500\u2500 Anims\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 _Compiled\n \u251c\u2500\u2500 Meshes\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 _Compiled\n \u251c\u2500\u2500 Music\n \u251c\u2500\u2500 Presets\n \u251c\u2500\u2500 Scripts\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 _compiled\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 content\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 CUTSCENE\n \u251c\u2500\u2500 Sound\n \u251c\u2500\u2500 Textures\n \u251c\u2500\u2500 Video\n \u2514\u2500\u2500 Worlds\n
"},{"location":"zengin/general_info/directory_structure/#data","title":"Data
","text":"Data directory contains .vdf
volumes of the game. These contain anims.vdf
- animations, speech.vdf
- dubbing, worlds.vdf
- world ZEN files.
"},{"location":"zengin/general_info/directory_structure/#saves","title":"Saves
","text":"Contains saved games.
"},{"location":"zengin/general_info/directory_structure/#system","title":"System
","text":"The system directory contains the game executable, GothicStarter.exe
, GothicStarter_mod.exe
, configuration .ini
files, mod .ini
files and mod icons and description .rtf
files.
system/Autorun
is a Union specific directory, it serves as a default search directory for Daedalus injection scripts with zParserExtender and Union plugins.
"},{"location":"zengin/general_info/directory_structure/#_workdata","title":"_work/DATA
","text":"This is where the magic happens:
Anims
- contains animations and animated models. _compiled
- contains compiled animations. Meshes
- contains meshes source and compiled files. _compiled
- contains compiled meshes. Music
- contains music files. Presets
- contains basic presets. Scripts
_compiled
- contains compiled scripts - .dat
files. Content
- contains scripts that make up the content of the game. System
- contains scripts that make up the menu. Sound
- contains sound effects .wav
or .ogg
format (Union only). Video
- contains videos in .bik
format. "},{"location":"zengin/general_info/object_persistence/","title":"Object persistence","text":""},{"location":"zengin/general_info/object_persistence/#object-persistence","title":"Object persistence","text":"In order to simplify the process of loading and saving data of various types to and from the user's hard-drive, ZenGin implements a simple object persistence system using the zCArchiver
class and its derivatives that allow the individual engine classes to implement a routine specifying which data should be saved or loaded from disk and in which manner.
An object that is derived from the zCObject
class may overload the Archive
and Unarchive
virtual methods. The class may then call on an interface provided by the zCArchiver
class within these methods which allows it to directly read from or write to a stream using several modes. Those are ASCII and BinSafe by default. There are, however, more options, as is explained below.
"},{"location":"zengin/general_info/object_persistence/#archive-format","title":"Archive format","text":"In order to better understand how this process works, it would be best to look at an example of a .ZEN file containing an instance of an oCWorld
object.
"},{"location":"zengin/general_info/object_persistence/#header","title":"Header","text":"When you open up a ZenGin archive, you will see the following at the start of the file:
ZenGin Archive\nver 1\nzCArchiverGeneric\nASCII\nsaveGame 0\ndate 7.1.2001 23:9:19\nuser roeske\nEND\nobjects 2594 \nEND\n
Let's look at each of these properties and what they mean:
ZenGin Archive
This simply specifies that the following data is an zCArchiver
archive.
ver 1
Version specification. Can be either 0
or 1
. Both Gothic 1 and 2 are already on version 1, although version 0 archives can also be occasionally found.
zCArchiverGeneric
Specifies which derived zCArchiver
class should be used to read this archive. Accepted values are zCArchiverGeneric
for ASCII and Binary archives, and zCArchiverBinSafe
for BinSafe archives. More info below. This property might not be present in older archives.
ASCII
This is the most important part of the header as it specifies in which format should the data be stored. There are 4 different modes:
ASCII - The simplest one. It stores data in human-readable ASCII notation (not unlike JSON for example). This is usually used when saving data during development and/or testing, while the final version of said data will most likely be stored as BIN_SAFE. ASCII_PROPS - Same as ASCII except with more additional data that the developer can specify for visual clarity. In practice, it is not used anywhere and mostly serves only to prettify debug info (try typing ZWORLD VOBPROPS
in the console and look in zSpy ;) ). BINARY - Binary representation of the class instance, which mostly copies the data 1:1 into/from the stream. In practice, this format is only used to store savefiles (.SAV). BIN_SAFE - BinSafe, short for Binary Safe, is an extended version of Binary which stores type information along with the data itself. This is meant to make error checking for invalid data easier. There are other changes which are explained below. Most, if not all world files (.ZEN), are stored in this format. saveGame 0
Specifies if this archive is a savefile. This property might not be present in older archives.
date 7.1.2001 23:9:19
The date at which this archive was created.
user roeske
The user which created the archive. This property might not be present in older archives.
END
Tells the parses that this is the end of the header.
We may additionally find a property called csum
in version 0 archives which stores the checksum of the whole archive. This property is, however, unused and equals 00000000
by default.
In order to correctly read the archive's header across varying engine versions, one should not count on the properties always being in the same order or even being there at all.
If the archive utilizes zCArchiverGeneric
then this header will also be followed by a short section specifying the number of object instances in this archive. This value will be used to initialize the objectList, which is an array of pointers where the addresses of loaded objects will be stored for later referencing. This property would be directly part of the main header in older versions.
objects 2594 END \n
If the archive is created using zCArchiverBinSafe
, this data will be stored in the following binary structure:
struct BinSafeArchiveHeader \n{ \n uint32_t version; // Always equals 2 uint32_t objectCount; // Serves the same function as \"objects n\" uint32_t chunkPos; // Offset to chunk hash table};\n}; \n
"},{"location":"zengin/general_info/object_persistence/#contents","title":"Contents","text":"Looking further into the archive, we see what appears to be a nested structure.
[% oCWorld:zCWorld 64513 0]\n [VobTree % 0 0]\n childs0=int:1\n [% zCVobLevelCompo:zCVob 12289 1]\n pack=int:0\n presetName=string:\n bbox3DWS=rawFloat:-71919.9609 -13091.8232 -59900 108999.992 20014.0352 67399.9922 \n trafoOSToWSRot=raw:0000803f0000000000000000000000000000803f0000000000000000000000000000803f\n trafoOSToWSPos=vec3:0 0 0\n vobName=string:LEVEL-VOB\n visual=string:SURFACE.3DS\n showVisual=bool:0\n visualCamAlign=enum:0\n cdStatic=bool:1\n cdDyn=bool:0\n staticVob=bool:0\n dynShadow=enum:0\n [visual zCMesh 0 2]\n []\n [ai % 0 0]\n []\n []\n ...\n
We primarily differentiate between chunks and properties within ZenGin archives:
"},{"location":"zengin/general_info/object_persistence/#chunks","title":"Chunks","text":"A chunk is a structure that groups properties together. For most of the time, a chunk represents a class instance. This is, however, not always true as classes may arbitrarily create chunks as is needed. For example, the sample above contains a chunk called VobTree
, which does not represent a class instance, but only serves to make the reading of the archive easier.
While in ASCII mode, the start of a chunk is represented using square brackets.
[% oCWorld:zCWorld 64513 0]
There are 4 pieces of data separated by spaces inside the start of each chunk, which are:
Object name - The name of the chunk to use while reading. If the chunk has no name, then it will be simply equal to %
. Class name - The name of the class which this chunk represents. Class names are stored with their full inheritance hierarchy (e.g. oCMobLadder:oCMobInter:oCMOB:zCVob
). In case the chunk is not an object, but an arbitrary chunk, then this field will be equal to %
(%
can also mean that this chunk is a nullptr). In some cases you may encounter the symbol \u00a7
instead. This means that the object already exists and that the parser should look for it in the objectList using the object index. Using this mechanism, a single instance can be referenced multiple times without worrying about duplicity. Class version - Used to ensure that the data being read is compatible with the current game/engine version, so that there are no mismatches in the data pattern. This value is different for every class and varies between game versions. Object index - An index into the objectList under which this object will be stored. If the class name is equal to \u00a7
, then this value will be used to retrieve an existing instance from the objectList. If this is a Binary archive, the same data will be stored in the following binary structure:
struct BinaryObjectHeader\n{\n uint32_t objectSize; // Size of the whole object in bytes\n uint16_t classVersion;\n uint32_t objectIndex;\n char objectName[]; // Null-terminated string\n char className[]; // Null-terminated string\n};\n
Oddly enough, if the archive is BinSafe, then the data will be encoded the same way as in ASCII mode, except that it will be stored as a type-checked property.
struct BinSafeObjectHeader\n{\n uint32_t type; // 0x1 = TYPE_STRING\n uint16_t length; // Length of the text\n char text[]; // [% oCWorld:zCWorld 64513 0]\n};\n
In ASCII mode []
represents the end of the current chunk.
"},{"location":"zengin/general_info/object_persistence/#properties","title":"Properties","text":"We find properties inside the chunks which are key-value pairs that classes use to store the actual data. Each property stores its name, type and value. In ASCII mode the format for this isname=type:value
.
For example:
visual=string:SURFACE.3DS
By default, zCArchiver
allows to store properties of the following types:
Int - A regular 32-bit integer. In ASCII mode, int gets stored as name=int:1
, while in Binary mode, it's just the raw value stored as 4 bytes.
Byte - A 8-bit integer. ASCII mode doesn't differentiate between Int and Byte, so this will be stored as name=int:1
regardless. Binary mode stores only the single byte.
Word - A 16-bit integer. ASCII mode doesn't differentiate between Int and Word, so this will be stored as name=int:1
regardless. Binary mode stores only the 2 bytes.
Float - A standard IEEE 754 32-bit floating point number. In ASCII mode the format is name=float:1.0
, while in Binary mode the float gets stored raw as 4 bytes.
Bool - Stores a single-byte boolean value. In ASCII mode its name=bool:1
and in Binary mode it's a single byte.
String - An ASCII encoded string. While in ASCII mode, strings are stored as name=string:value
. In Binary mode, strings are NULL terminated.
Vec3 - A three component vector, mainly used to store positional data. The ASCII mode format is name=vec3:1.0 1.0 1.0
. In Binary mode the three components of the vector are stored in series, which equals to a total size of 12 bytes.
Color - A 32-bit color value stored as BGRA. In ASCII mode the color is stored as name=color:255 255 255 255
while in Binary mode it's just 4 raw bytes.
Raw - Raw binary data. In order to maintain readability, in ASCII mode this gets stored as a hex encoded string such as name=raw:63D15B07
. In Binary mode, only the data itself is stored, without any other info. Be aware that due to this you must know the size of the data beforehand.
RawFloat - An array of floats, mainly used to store bounding boxes. In ASCII mode, the floats are stored as name=rawFloat:1.0 1.0 1.0 1.0 1.0 1.0
. In Binary mode the floats are stored in series as raw bytes. Same as with Raw
, you must know the size of the array beforehand.
Enum - An enum value. In ASCII mode, it gets stored as name=enum:1
. In Binary mode, it behaves the same as Int
.
As you might have noticed, binary mode doesn't perform any kind of checks on if it's reading the right property or even data of the correct type. This is why BinSafe mode exists, as it stores the property type in along with the data itself.
enum TYPE\n{\n TYPE_STRING = 0x1,\n TYPE_INTEGER = 0x2,\n TYPE_FLOAT = 0x3,\n TYPE_BYTE = 0x4,\n TYPE_WORD = 0x5,\n TYPE_BOOL = 0x6,\n TYPE_VEC3 = 0x7,\n TYPE_COLOR = 0x8,\n TYPE_RAW = 0x9,\n TYPE_RAWFLOAT = 0x10,\n TYPE_ENUM = 0x11\n TYPE_HASH = 0x12,\n};\n\nstruct BinSafeProperty\n{\n TYPE type;\n union\n {\n struct\n {\n uint16_t stringLength;\n char stringValue[];\n }\n uint32_t integerOrHashOrEnumValue;\n float floatValue;\n uint8_t byteOrBoolValue;\n zVEC3 vec3Value;\n zCOLOR colorValue;\n struct\n {\n uint16_t rawLength;\n char rawValue[];\n }\n struct\n {\n uint16_t rawFloatLength;\n float rawFloatValue[];\n } \n };\n};\n
Looking at the enumeration of types, you might notice that BinSafe mode has an additional property type called Hash. BinSafe archives include a hash table which is stored in the following manner:
struct BinSafeHashTable\n{\n uint32_t chunkCount;\n for (chunkCount)\n {\n uint16_t stringLength;\n uint16_t linearValue;\n uint32_t hashValue;\n char text[stringLength];\n }\n};\n
Instead of storing the raw value, properties may save a hash instead, which is then used to look up the corresponding value from the hash table.
"},{"location":"zengin/general_info/object_persistence/#implementation","title":"Implementation","text":"As mentioned in the opening paragraph, classes may use the described functionality by overloading the Archive
and Unarchive
virtual methods, which pass an instance of zCArchiver
by reference. When the class instance is then serialized and/or parsed, these methods are called and perform the desired serialization/parsing work.
The class uses methods provided by the zCArchiver
instance within these routines. These methods return/accept a value of a specific type (e.g. ReadInt/WriteInt), while they do the actual reading/writing work behind the scenes based on the current mode (ASCII/Binary/BinSafe). The programmer writing the class then does not care whether the final archive will be saved as ASCII, Binary or BinSafe, as they only use the zCArchiver
Read* and Write* methods.
"},{"location":"zengin/general_info/object_persistence/#a-practical-example","title":"A practical example","text":"Let's propose that we have a class which is declared like so:
class zCMyClass : public zCObject\n{\npublic:\n\n zCMyClass() {}\n virtual ~zCMyClass() {}\n\n virtual void Archive(zCArchiver&);\n virtual void Unarchive(zCArchiver&);\n\n int myInt;\n zCMyClass* myObject;\n zCMyClass* secondPointerToMyObject;\n\n};\n
The hypothetical class then implements these virtual functions:
void zCMyClass::Archive(zCArchiver& archiver)\n{\n archiver.WriteInt(\"myInt\", myInt);\n\n archiver.WriteObject(\"myObject\", myObject);\n\n archiver.WriteChunkStart(\"myChunk\", 0);\n archiver.WriteObject(\"secondPointerToMyObject\", secondPointerToMyObject);\n archiver.WriteChunkEnd();\n}\n\nvoid zCMyClass::Unarchive(zCArchiver& archiver)\n{\n archiver.ReadInt(\"myInt\", myInt);\n\n myObject = dynamic_cast<zCMyClass*>(archiver.ReadObject(\"myObject\"));\n\n archiver.ReadChunkStart(\"myChunk\");\n secondPointerToMyObject = dynamic_cast<zCMyClass*>(archiver.ReadObject(\"secondPointerToMyObject\"));\n archiver.ReadChunkEnd();\n}\n
We then initialize the class in the following way:
zCMyClass object;\n\nobject.myInt = 12121212;\n\nobject.myObject = new zCMyClass();\nobject.myObject->myInt = 34343434;\n\nobject.secondPointerToMyObject = object.myObject;\n
If we now serialized, or to use the engine's term \"archived\", this instance into an ASCII archive, the result would look like this:
ZenGin Archive\nver 1\nzCArchiverGeneric\nASCII\nsaveGame 0\ndate 3.7.2022 0:0:0\nuser GMC\nEND\nobjects 2 \nEND\n\n[% zCMyClass 0 0]\n myInt=int:12121212\n [myObject zCMyClass 0 1]\n myInt=int:34343434\n [myObject % 0 0]\n []\n [myChunk % 0 0]\n [secondPointerToMyObject % 0 0]\n []\n []\n []\n [myChunk % 0 0]\n [secondPointerToMyObject \u00a7 0 1]\n []\n []\n[]\n
Notice how secondPointerToMyObject
doesn't have any contents. The character \u00a7
tells the parser that this object already exists in the objectList, and that instead of creating a new instance, it should return an existing instance which is stored under index 1
in the objectList. This allows an instance to be referenced from multiple places, without the need to worry about duplicity.
If we used Binary or BinSafe mode, we would see a big blob of binary data instead. This would, of course, store the exact same data, although in a slightly less human-readable format.
"},{"location":"zengin/general_info/object_persistence/#final-thoughts","title":"Final thoughts","text":"We hope this helps you better understand the inner workings of ZenGin. If you want to see how Piranha Bytes went about implementing a much more advanced version of this system for their next engine, check out Genome's object persistence system.
"},{"location":"zengin/general_info/vdfs/","title":"VDFS virtual file system","text":""},{"location":"zengin/general_info/vdfs/#vdfs-virtual-file-system","title":"VDFS virtual file system","text":"VDFS is the virtual file system used by ZenGin to distribute and store many, but not all, game assets.
Learn more
If you want a more technical documentation of the VDFS format, you can find it on ZenKit site.
"},{"location":"zengin/general_info/vdfs/#loading","title":"Loading","text":""},{"location":"zengin/general_info/vdfs/#vdf","title":"VDF","text":".vdf
files can usually be found in the Data/
directory of Gothic installations and the game loads them automatically.
Volumes are loaded based on the timestamp specified inside the .vdf
file. The volumes with the latest timestamp are loaded first.
"},{"location":"zengin/general_info/vdfs/#mod","title":"MOD","text":".mod
files are stored in the Data/ModVDF/
directory and loaded when they are specified in the current game .ini
.
MyMod.ini// [...]\n[FILES]\nVDF=MyMod.mod MyMod_Textures.mod\n// [...]\n
"},{"location":"zengin/general_info/vdfs/#tools","title":"Tools","text":"The community created variety of different modding tools for work with VDFS volumes over the times, such as:
"},{"location":"zengin/general_info/vdfs/#gothicvdfs","title":"GothicVDFS","text":"Most popular tool for working with VDFS volumes. Allows viewing, extracting and building .vdf
and .mod
archives, and has CLI interface.
"},{"location":"zengin/general_info/vdfs/#vdfs-tool","title":"VDFS Tool","text":"New tool for working with VDFS volumes, created to support features introduced by Union. Apart from viewing, extracting and building .vdf
and .mod
archives, it also supports optimizing and compressing them.
"},{"location":"zengin/meshes/","title":"Meshes","text":""},{"location":"zengin/meshes/#meshes","title":"Meshes","text":"In 3D graphics, meshes are collections of vertices, edges, and faces that create 3D objects. ZenGin use meshes to create the world model and objects in the world.
Info
Not all objects that seem to be a mesh are in the \"Meshes\" category. Except every animated objects, the animation targets (like beds or doors) also belong to the Animations.
"},{"location":"zengin/meshes/#formats","title":"Formats","text":""},{"location":"zengin/meshes/#raw","title":"Raw","text":"ZenGin uses the .3ds
file format for raw source meshes. That is one of the file formats used by the Autodesk 3ds Max, which was used by the Gothic developers.
The .3ds
files can be opened with any 3D modeling software that supports this format. But, to easily import/export them with engine-specific settings, it is recommended to use Blender 2.80+ with the KrxImpExp extension.
3DS limitations
The 3DS format has some disadvantages when building levels. With very large levels such as SURFACE.3DS
, you reach the upper limit of 65,536 polygons per object that are permitted in a .3ds
file. To get around this problem, proceed as follows: simply \u201ccut\u201d the mesh into several small parts that are below the 64K poly limit. For example, the SURFACE.3DS
was dismantled into 4 parts of roughly equal size and then completely exported. This mesh is then melted together again into an object in the spacer. This happens due to overlapping vertices.
"},{"location":"zengin/meshes/#compiled","title":"Compiled","text":"Source formats are great for editing, but can be a bit heavy for the engine use (ASCII based formats are slower to parse and work with), because of that ZenGin compiles these meshes into internal compiled formats. In the case of the world it is .MSH
format and in the case of objects in the world it is the .MRM
(multi resolution mesh) with LOD information
"},{"location":"zengin/meshes/#tools","title":"Tools","text":""},{"location":"zengin/meshes/#krximpexp","title":"KrxImpExp","text":"Blender add-on that implements support for Gothic 3D formats.
Download
"},{"location":"zengin/meshes/#zenkit","title":"ZenKit","text":"C++ Library for loading and saving various ZenGin files (including some 3D formats).
Read More
"},{"location":"zengin/meshes/water/","title":"Water","text":""},{"location":"zengin/meshes/water/#water","title":"Water","text":"Water in ZenGin is a special surface. Therefore, there are some rules that have to be followed, to make it work properly.
"},{"location":"zengin/meshes/water/#water-modeling","title":"Water Modeling","text":"Water is created in Gothic using a double-sided tarp that is assigned a water material. This means you have to create a surface with the normal pointing upwards and the same surface facing downwards again. There must be a floor under the water tarp, otherwise you won't be able to swim. It also makes sense not to connect the double-sided water tarpaulin to the coast, otherwise the coast will follow the wave movement of the water. It's best to let the water run a little into the coast so that the wave movements don't create holes between the water and the coast.
"},{"location":"zengin/meshes/water/#segmentation","title":"Segmentation","text":"You should segment (divide) the water surface for the following reasons:
Performance: Areas are always calculated in their entirety. If the area is too large, unnecessary areas (e.g. under an island) are also calculated, which additionally deducts computing power. By segmenting you can delete areas of water that are not visible. Display error: The entire area is also displayed. However, if the end is out of sight, the water may flicker. Wave movement: The up and down movement of the water takes place at the corners of the water surfaces. If you have smaller areas, the waves are also more precise. In addition, an area that is too large may not work at all, meaning you can walk on it or even fall over. Water is a big power drain. It is advisable to make the segments towards the coast smaller and smaller so that an unnecessary number of areas in the distance do not have to be calculated, but the wave movement on the coast still looks fine enough. Here are two examples of possible segmentation of the water surface (in Blender):
In the example on the left, the water area was created from squares that get smaller the closer they are to the coast. Since Gothic automatically divides the squares into triangles anyway, the example on the right makes even more sense. The water surface was created from a hexagon and consists of whole or halved equilateral triangles. In addition, the outer boundary of the water is at a more even distance from the coast. In both examples, the segments in the middle of the island are deleted.
"},{"location":"zengin/meshes/water/#water-material-properties","title":"Water Material Properties","text":"To be able to swim in water, you need to place a water material on the double-sided water surfaces. By default, without changing any material settings the water will be frozen. To change that you have to edit zCMaterial settings in Spacer.
Tip
You can also place different water materials on the top and bottom.
The most important property - the one that tells the engine that the material is a water and player can swim in it - is matGroup. It has to be set to WATER
.
To make water look like actual water consider changing following parameters:
color - Material color. Something like 150 241 238 200
(in RGBA) will add a little transparency and blue \"glow\". texAniFPS - Speed at which the animation of the texture should be played. texAniMapDir - Speed at which the texture should be moved in the x or y direction (useful for waterfalls and rivers). Some parameters have only been available since Gothic 2:
environmentalMapping - Simulation of a reflection of the surface. environmentalMappingStrength - Strength of surface reflection. waveMode - Type of wave motion. waveSpeed - Wave speed. The higher the value, the faster the waves move. waveMaxAmplitude - Wave height. waveGridSize - Wave expansion. This article is mostly a translation of the one posted on Gothic Editing Wiki \u21a9
"},{"location":"zengin/scripts/","title":"Scripts","text":""},{"location":"zengin/scripts/#scripts","title":"Scripts","text":"ZenGin uses its own scripting language called Daedalus. It is similar to C programming language, so if you know some C programming, it will be quite easy to get started.
The Scripts
directory is where the scripts live. You will be able to find Daedalus script files - .d
extension and .src
files, that list all files to be compiled.
Daedalus scripts can be edited in any text editor. To get useful features like syntax highlighting you can use community developed tools like
Gothic Sourcer Daedalus VS Code extension "},{"location":"zengin/scripts/classes/c_info/","title":"C_INFO Daedalus class","text":""},{"location":"zengin/scripts/classes/c_info/#c_info-daedalus-class","title":"C_INFO Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library.
The C_INFO
class is used to define dialogues in the game.
"},{"location":"zengin/scripts/classes/c_info/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/Content/_intern/Classes.d
script file.
C_Info Daedalus class class C_Info\n{\n var int npc; // npc instance has the dialogue\n var int nr; // number of the dialogue (for sorting)\n var int important; // should the npc start the dialogue automatically\n var func condition; // condition function\n var func information; // function called on selecting the dialogue\n var string description; // text in the dialogue box\n var int trade; // should the dialogue show the trade window\n var int permanent; // should the dialogue be permanent or only one time deal\n};\n
"},{"location":"zengin/scripts/classes/c_info/#class-members","title":"Class members","text":"Variable Type Description npc int npc instance to have the dialogue nr int dialogue order number important int npc addresses player automatically condition func condition function whether the dialogue is shown or not information func function called on dialogue selection - contains the dialogue lines and other logic description string text shown in the dialogue box trade int is it a trade dialogue permanent int does the dialogue stay after being played once"},{"location":"zengin/scripts/classes/c_info/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_info/#npc","title":"npc","text":"Sets what NPC will have this dialogue instance. Set an NPC instance.
instance Info_Diego_Gamestart (C_INFO)\n{\n npc = PC_Thief; // NPC instance for Diego\n // ...\n};\n
"},{"location":"zengin/scripts/classes/c_info/#nr","title":"nr","text":"The nr
member variables determines the order of shown dialogues. Dialogues are ordered in the ascending order - instances with higher nr
are below instances with lower nr
.
instance Info_Diego_Gamestart (C_INFO)\n{\n // ...\n nr = 1;\n // ...\n};\n
Note
This is why the end dialogues usually have nr = 999;
this is the highest number out of any dialogues therefore will always show up at the bottom. (999 is not the highest number the nr
can store, it is just considered the highest number, as there will hardly be 998 dialogue instances for a single character)
"},{"location":"zengin/scripts/classes/c_info/#important","title":"important","text":"The important
member variable determines whether the NPC will automatically address the player or not.
important = TRUE
- the NPC will address the player important = FALSE
- the player has to talk to the NPC When important
is set to TRUE
, the description is not needed since the dialogue is never shown in the dialogue box.
Info
If there are multiple important dialogues that satisfy their condition function, they will be played in the order specified by nr
.
Tip
important
variable is of the type integer, and it is initialized by the engine to the value of 0
. If you do not want your dialogue to be important, you can omit the important
member variable since it will be initialized to 0
by the engine.
"},{"location":"zengin/scripts/classes/c_info/#condition","title":"condition","text":"Condition function with signature func int f()
. If the function returns TRUE
the dialogue is displayed, if it returns FALSE
it is not displayed. The function name does not have to follow a particular naming convention, but a naming convention is used throughout all the Gothic scripts: {DialogueName}_Condition
.
Conditioned dialogueUnconditioned dialogue instance Info_Diego_Gamestart (C_INFO)\n{\n // ...\n condition = Info_Diego_Gamestart_Condition;\n // ...\n};\n\nfunc int Info_Diego_Gamestart_Condition()\n{\n if (Kapitel < 2) // Show only when chapter is less than 2\n {\n return TRUE;\n };\n return FALSE; // Not needed, but added for readability\n};\n
instance Info_Diego_EXIT_Gamestart(C_INFO)\n{\n // ...\n condition = Info_Diego_EXIT_Gamestart_Condition;\n // ...\n};\n\nfunc int Info_Diego_EXIT_Gamestart_Condition()\n{\n return TRUE; // or return 1;\n};\n
Tip
It is unnecessary to return FALSE
from dialogue conditions, but in other cases it can very rarely cause subtle bugs. It is thus good practice to always return some value, even if that is FALSE
.
"},{"location":"zengin/scripts/classes/c_info/#information","title":"information","text":"The information
function contains the function name (without double quotes \"\"
as func
is a type in Daedalus) that is called when the dialogue option is selected. It contains the lines NPCs will say, items that will be transferred, quests related logic and much more. The function name does not have to follow a particular naming convention, but a naming convention is used throughout all the Gothic scripts: {DialogueName}_Info
.
instance Info_Diego_Gamestart (C_INFO)\n{\n npc = PC_Thief;\n nr = 1;\n condition = Info_Diego_Gamestart_Condition;\n information = Info_Diego_Gamestart_Info;\n permanent = FALSE;\n important = TRUE;\n};\n\nfunc int Info_Diego_Gamestart_Condition()\n{\n if (Kapitel < 2)\n {\n return TRUE;\n };\n return FALSE;\n};\n\nfunc void Info_Diego_Gamestart_Info()\n{\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_00\"); //I'm Diego.\n AI_Output(hero,self,\"Info_Diego_Gamestart_15_01\"); //I'm...\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_02\"); //I'm not interested in who you are. You've just arrived. I look after the new arrivals. That's all for now.\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_03\"); //If you plan to stay alive for a while, you should talk to me. But of course I won't keep you from choosing your own destruction. Well, what do you think?\n\n B_Kapitelwechsel(1); // Show the chapter 1 screen\n};\n
"},{"location":"zengin/scripts/classes/c_info/#description","title":"description","text":"Specify a string that will be shown in the dialogue window.
instance DIA_XARDAS_GMC(C_INFO)\n{\n // ...\n description = \"Hello, is this the GMC site?\";\n};\n
"},{"location":"zengin/scripts/classes/c_info/#trade","title":"trade","text":"If trade
is set to TRUE
the trading interface will be launched after the content information
function is finished.
Fisk's trade dialogueinstance Stt_311_Fisk_Trade (C_INFO)\n{\n npc = Stt_311_Fisk;\n nr = 800;\n condition = Stt_311_Fisk_Trade_Condition;\n information = Stt_311_Fisk_Trade_Info;\n permanent = TRUE;\n description = \"Show me your goods.\";\n trade = TRUE;\n};\n\nfunc int Stt_311_Fisk_Trade_Condition()\n{\n return TRUE;\n};\n\nfunc void Stt_311_Fisk_Trade_Info()\n{\n AI_Output (other, self, \"Stt_311_Fisk_Trade_15_00\"); //Show me your goods.\n};\n
Trivia
Trade manager has been added to ZenGin not that long before the release of Gothic 1 (as discussed and discovered on Phoenix the Game Discord server with the acquisition of Gothic version 0.94k
). In version 0.94 the trade manager worked quite differently and used a special (nowadays unused) Daedalus class C_ItemReact
.
"},{"location":"zengin/scripts/classes/c_info/#permanent","title":"permanent","text":"Dialogues with permanent = TRUE
do not disappear after the dialogue is played. This is used for dialogues where you ask for directions or flavor dialogues for unnamed NPCs.
Bug
Frequently used external function Npc_KnowsInfo
which returns true if the dialogue instance has been played has had a bug in the implementation for a long time. This bug made it impossible to use this function with dialogue instances with permanent = TRUE
as it would always return FALSE
. This has been fixed in Union 1.0m
.
"},{"location":"zengin/scripts/classes/c_info/#lego","title":"LeGo","text":"LeGo implements a lot of useful functions for dialogues. It makes it possible to create Trialogues and change NPCs behaviour by Dialoggestures. Moreover, any Daedalus function can be added to NPCs AI queue via the AI_Function package.
"},{"location":"zengin/scripts/classes/c_info/#zparserextender","title":"zParserExtender","text":"zParserExtender implements some Quality of Life features for dialogues. More information can be found in Dialogue constants article.
"},{"location":"zengin/scripts/classes/c_info/#af-script-packet","title":"AF Script Packet","text":"Enhanced Info Manager (implemented using Ikarus and LeGo) adds tons of customizations and additional features to dialogues. More information can be found in the AFSP Enhanced Information Manager article.
"},{"location":"zengin/scripts/classes/c_item/","title":"C_ITEM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_item/#c_item-daedalus-class","title":"C_ITEM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
The C_ITEM
class is used to define new items in the game.
"},{"location":"zengin/scripts/classes/c_item/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/Content/_intern/Classes.d
script file.
C_Item Daedalus class class C_Item\n{\n // For all Items\n var int id; // ID of the item\n var string name; // Name of the item\n var string nameID; // Name ID\n var int hp; // Current health of the item\n var int hp_max; // Maximum health of the item\n\n var int mainflag; // Item category flag\n var int flags; // Item type flag\n var int weight; // Weight of the item\n var int value; // Value of the item\n\n // For weapons\n var int damageType; // Damage type\n var int damageTotal; // Total amount of damage\n var int damage[DAM_INDEX_MAX]; // Array of damage types\n\n // For armours\n var int wear; // Flag to specify where to wear an item\n var int protection[PROT_INDEX_MAX]; // Protection array of different damage types\n\n // For food\n var int nutrition; // The amount of HP healed\n\n // Ben\u00f6tigte Attribute zum Benutzen des Items\n var int cond_atr[3]; // Array of NPC attributes needed to equip the item\n var int cond_value[3]; // Array of values corresponding to the cond_atr array\n\n // Attributes to be changed on equip\n var int change_atr[3]; // Array of attributes that will be changed on equip\n var int change_value[3]; // Array of values of the attributes defined in change_atr\n\n // Parser functions\n var func magic;\n var func on_equip; // Called on equpping an item\n var func on_unequip; // Called on unequipping an item\n var func on_state[4];\n\n var func owner; // Owner of the item: instance name\n var int ownerGuild; // Owner of the item: guild\n var int disguiseGuild; // NPC guild set when equipping an item\n\n // 3DS model file\n var string visual; // Item model file\n\n // NPC mesh change, when equipping an item\n var string visual_change; // .asc file\n var string effect; // Effect instance\n\n var int visual_skin; // Texture variation\n\n var string scemeName; // Animation sceme name\n var int material; // Material of the object\n\n var int munition; // Ammo instance\n\n var int spell; // ID if the spell that this item does\n var int range; // Range of the weapon\n\n var int mag_circle; // Circle of magic needed to use this item\n\n var string description; // The name of the item shown in the preview box\n var string text[ITM_TEXT_MAX]; // Array of string describing the item (left side)\n var int count[ITM_TEXT_MAX]; // Array of integers (the right side)\n\n // Parameters for displaying items in the inventory\n var int inv_zbias // How far away is the item from the screen\n var int inv_rotx // X-axis rotation\n var int inv_roty // Y-axis rotation\n var int inv_rotz // Z-axis rotation\n var int inv_animate // Should the item rotate in the inventory\n};\n
It has many member variables but not all of them are used for every item. It is not necessary to define every one of these variables for every item as it was discussed on InsideGothic.
"},{"location":"zengin/scripts/classes/c_item/#class-members","title":"Class members","text":"A selection of the most important class members.
"},{"location":"zengin/scripts/classes/c_item/#change_atr--change_value","title":"change_atr & change_value","text":"change_atr
stores the attributes that will be changed by the amount specified in change_value
.
NPCs have these attributes:
const int ATR_HITPOINTS = 0; // Hit points\nconst int ATR_HITPOINTS_MAX = 1; // Max hitpoints\nconst int ATR_MANA = 2; // Mana\nconst int ATR_MANA_MAX = 3; // Max mana\n\nconst int ATR_STRENGTH = 4; // Strength\nconst int ATR_DEXTERITY = 5; // Dexterity\nconst int ATR_REGENERATEHP = 6; // HP regeneration per second\nconst int ATR_REGENERATEMANA = 7; // Mana regeneration per second\n
This can be used on all equipable items to change the attributes. As an example we can create a sword that has a 10 point dexterity bonus.
instance ItMw_testSword (C_Item)\n{\n // some code\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n // some code\n};\n
Warning
Do not change ATR_HITPOINTS
, ATR_MANA
, ATR_HITPOINTS_MAX
or ATR_MANA_MAX
as it will result in unwanted behaviour with max health or max mana.
You can change ATR_HITPOINTS_MAX
and ATR_MANA_MAX
attributes in on_equip and on_unequip
"},{"location":"zengin/scripts/classes/c_item/#cond_atr--cond_value","title":"cond_atr & cond_value","text":"cond_atr
stores the attributes that will be checked as a requirement to equip an item, the amount specified in cond_value
.
The next example sword is equipable only if the NPC has at least 5 strength. If the requirements are not met G_CanNotUse()
is called.
instance ItMw_testSword (C_Item)\n{\n // some code\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n // some code\n};\n
Try injecting the code below zParserExtender to test it in game right away. It is compatible with G2NotR.
instance ItMw_testSword (C_Item)\n{\n name = TXT_Spells[10]; // demonstrates the usage of direct constr array access\n\n mainflag = ITEM_KAT_NF;\n flags = ITEM_SWD;\n material = MAT_METAL;\n\n value = 10;\n\n damageTotal = 10;\n damagetype = DAM_EDGE;\n range = 100;\n\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n\n visual = \"ItMw_010_1h_Sword_short_01.3DS\";\n\n description = name;\n\n TEXT[2] = NAME_Damage; COUNT[2] = damageTotal;\n TEXT[3] = NAME_Str_needed; COUNT[3] = cond_value[2];\n TEXT[4] = NAME_OneHanded;\n TEXT[5] = NAME_Value; COUNT[5] = value;\n};\n
To insert it into the game use insert ItMw_testSword
in console."},{"location":"zengin/scripts/classes/c_item/#text--count-arrays","title":"text & count arrays","text":"These two arrays are used to put information into the item information box. The maximum number of lines is 6. This is defined in the engine, but for script side class definition is declared in the scripts too.
const int ITM_TEXT_MAX = 6;\n
This example shows an item with all elements of TEXT
and COUNT
array filled. Note
Please notice the last COUNT
element. It did not take the value we entered, but shows 10
which is the value
of the item. This behaviour can be changed with Ikarus or Union.
You can find the code below
instance ItMw_testSword (C_Item)\n{\n name = TXT_Spells[10];\n\n mainflag = ITEM_KAT_NF;\n flags = ITEM_SWD;\n material = MAT_METAL;\n\n value = 10;\n\n damageTotal = 10;\n damagetype = DAM_EDGE;\n range = 100;\n\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n\n visual = \"ItMw_010_1h_Sword_short_01.3DS\";\n\n description = name;\n\n TEXT[0] = \"Line 0\"; COUNT[0] = 0; \n TEXT[1] = \"Line 1\"; COUNT[1] = 1; \n TEXT[2] = \"Line 2\"; COUNT[2] = 2; \n TEXT[3] = \"Line 3\"; COUNT[3] = 3; \n TEXT[4] = \"Line 4\"; COUNT[4] = 34;\n TEXT[5] = \"Line 5\"; COUNT[5] = 35;\n};\n
"},{"location":"zengin/scripts/classes/c_item/#description--name","title":"description & name","text":"description
- determines the name of the item in the inventory
name
- determines the focus name of the item in the world
In the scripts you often find that the description is assigned the value of name
.
instance ItMw_testSword (C_Item)\n{\n name = \"New amazing sword\";\n // ...\n description = name; // description now has the same value as ' // ...name'\n // ...\n};\n
This is used in the case where you want to show the name of the item on focus too. There is a second way used in the scripts though with, for example,magic scrolls - the focus name in the world is \"Scroll\" and in inventory the scroll carries the name of the spell. This is how it is done:
instance ItSc_InstantFireball (C_Item)\n{\n name = NAME_Spruchrolle; // const string = \"Scroll\"\n // ...\n description = NAME_SPL_InstantFireball; // const string = \"Fireball\"\n // ...\n};\n
"},{"location":"zengin/scripts/classes/c_item/#hp--hp_max","title":"hp & hp_max","text":"Both of these parameters are unused.
Trivia
In alpha ZenGin versions the player was able to destroy objects. This feature was abandoned during the course of the development. This video shows the reconstruction of this feature.
"},{"location":"zengin/scripts/classes/c_menu/","title":"C_MENU Daedalus class","text":""},{"location":"zengin/scripts/classes/c_menu/#c_menu-daedalus-class","title":"C_MENU Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_Menu
is responsible for the behavior and properties of the game menus (options, save etc.).
"},{"location":"zengin/scripts/classes/c_menu/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Menu.d
script file.
C_Menu Daedalus class class C_Menu \n{\n var string backPic; // Menu background image\n var string backWorld; // Background ZEN-world of the game menu (Not used)\n var int posx; // The top left point of the menu on the screen horizontally (X-axis)\n var int posy; // The top left point of the menu on the screen vertically (Y-axis)\n var int dimx; // Menu width in virtual coordinates\n var int dimy; // Menu height in virtual coordinates\n var int alpha; // Menu transparency\n var string musicTheme; // Music track of the menu\n var int eventTimerMSec; // trigger time for the event EVENT_TIMER\n var string items[150]; // Menu items\n var int flags; // Menu flags\n var int defaultOutGame; // Menu item highlighted by default when the game is not running\n var int defaultInGame; // Menu item highlighted by default when the game is running\n};\n
"},{"location":"zengin/scripts/classes/c_menu/#class-members","title":"Class members","text":"Variable Type Description backPic string Menu background image backWorld string Background ZEN-world of the game menu (Not used) posx int The top left point of the menu on the screen horizontally (X-axis) posy int The top left point of the menu on the screen vertically (Y-axis) dimx int Menu width in virtual coordinates dimy int Menu height in virtual coordinates alpha int Menu transparency musicTheme string Music track of the menu eventTimerMSec int The timer that triggered the event in seconds items string Menu items flags int Menu flags defaultOutGame int Menu item highlighted by default when the game is not running defaultInGame int Menu item highlighted by default when the game is running"},{"location":"zengin/scripts/classes/c_menu/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_menu/#backpic","title":"backPic","text":"backPic
is just a name of background image of the menu in .tga
format.
"},{"location":"zengin/scripts/classes/c_menu/#backworld","title":"backWorld","text":"Deprecated setting
The background world of the game menu in .ZEN
format.
"},{"location":"zengin/scripts/classes/c_menu/#posx","title":"posx","text":"The horizontal position of the top left point of the menu on the screen, in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#posy","title":"posy","text":"The vertical position of the top left point of the menu on the screen, in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#dimx","title":"dimx","text":"Menu width in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#dimy","title":"dimy","text":"Menu height in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#alpha","title":"alpha","text":"Menu transparency. Accepts values \u200b\u200bfrom 0 to 255. Without the backPic
property specified, the value of this parameter is ignored.
Note
Texture transparency can only be adjusted if the texture has an alpha channel.
"},{"location":"zengin/scripts/classes/c_menu/#musictheme","title":"musicTheme","text":"Music theme of the menu.
instance MENU_MAIN(C_MENU_DEF)\n{\n ...\n musictheme = \"SYS_Menu\";\n ...\n};\n
All instances of musical themes are stored in a file Scripts/System/Music/MusicInst.d
"},{"location":"zengin/scripts/classes/c_menu/#eventtimermsec","title":"eventTimerMSec","text":"Defines the trigger time for the event EVENT_TIMER
in seconds.
The list of constants for all menu events is described in the file Scripts/System/_intern/Menu.d
const int EVENT_UNDEF = 0; // Undefined\nconst int EVENT_EXECUTE = 1; // Process start event\nconst int EVENT_CHANGED = 2; // Menu parameter change event\nconst int EVENT_LEAVE = 3; // Menu item focus loss event\nconst int EVENT_TIMER = 4; // Timer fire event\nconst int EVENT_CLOSE = 5; // Menu close event\nconst int EVENT_INIT = 6; // Initialization event\nconst int EVENT_SEL_PREV = 7; // Select event of the previous menu item\nconst int EVENT_SEL_NEXT = 8; // Select event of the next menu item\n
"},{"location":"zengin/scripts/classes/c_menu/#items","title":"items","text":"An array of items belonging to this menu. It is possible to use up to 150 items in one menu. The same elements can be used for different menus. The element instance is specified as the value.
// Menu\ninstance MENU_MAIN(C_MENU_DEF)\n{\n ...\n items[0] = \"MENUITEM_MAIN_HEADLINE\"; \n items[1] = \"MENUITEM_MAIN_HEADLINE2\";\n items[2] = \"MENUITEM_MAIN_NEWGAME\";\n ...\n};\n\n// Menu elements: labels, checkboxes, sliders, etc.\n\ninstance MENUITEM_MAIN_HEADLINE(C_MENU_ITEM_DEF)\n{\n ...\n};\n\ninstance MENUITEM_MAIN_HEADLINE2(C_MENU_ITEM_DEF)\n{\n ...\n};\n\ninstance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n ...\n};\n
"},{"location":"zengin/scripts/classes/c_menu/#flags","title":"flags","text":"Menu flags.
The list of flag constants can be found in the file Scripts/System/_intern/Menu.d
const int MENU_OVERTOP = 1; // Show menu over previous menu or in game\nconst int MENU_EXCLUSIVE = 2; // Close all previous menus. Only the active menu is displayed\nconst int MENU_NOANI = 4; // No animation\nconst int MENU_DONTSCALE_DIM = 8; // Don't Scale Menu Sizes\nconst int MENU_DONTSCALE_POS = 16; // Empty flag\nconst int MENU_ALIGN_CENTER = 32; // Center Align Menu\nconst int MENU_SHOW_INFO = 64; // Display information at the bottom of the description menu from menu items text[1]\n
MENU_OVERTOP - Flag to display the menu over the previous menu. It is not advisable to use with a transparent menu. MENU_EXCLUSIVE - Hide all menus except the active one. When closed, the previous menu is restored. MENU_NOANI - Animation of minimizing and maximizing windows. The game is mainly used for dialogue windows. You can't enable or disable the animation of dialog windows through scripts. This is done using the animatedWindows
setting in the Gothic.ini file. MENU_DONTSCALE_DIM - Scale the menu to fit 640x480 resolution. MENU_DONTSCALE_POS - Empty flag. Not used. MENU_ALIGN_CENTER - Align the menu to the center of the screen. MENU_SHOW_INFO - Display information at the bottom of menu description from menu item text[1]
. "},{"location":"zengin/scripts/classes/c_menu/#defaultoutgame","title":"defaultOutGame","text":"The menu item that is highlighted by default when the game is not running.
A value of -1 enables automatic selection of the first selectable element.
Items with the ~IT_SELECTABLE
flag are not selected.
"},{"location":"zengin/scripts/classes/c_menu/#defaultingame","title":"defaultInGame","text":"Menu item highlighted by default when the game is running.
A value of -1 enables automatic selection of the first selectable element.
Items with the ~IT_SELECTABLE
flag are not selected.
"},{"location":"zengin/scripts/classes/c_menuitem/","title":"C_MENU_ITEM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_menuitem/#c_menu_item-daedalus-class","title":"C_MENU_ITEM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_Menu_Item
describes the elements of the game menu (sliders, checkboxes, buttons, etc.) .
"},{"location":"zengin/scripts/classes/c_menuitem/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Menu.d
script file.
C_Menu_Item Daedalus class CONST INT MAX_USERSTRINGS = 10;\nCONST INT MAX_ITEMS = 150;\nCONST INT MAX_EVENTS = 10;\nCONST INT MAX_SEL_ACTIONS = 5;\nCONST INT MAX_USERVARS = 4;\n\nclass C_Menu_Item\n{\n var string fontName; // Font of the menu item.\n var string text[MAX_USERSTRINGS]; // Text of the interface element.\n var string backPic; // Background image of menu items.\n var string alphaMode; // Transparency blending mode of menu items.\n var int alpha; // Transparency of the menu item.\n var int type; // Type of the interface element.\n var int onSelAction[MAX_SEL_ACTIONS]; // Array of commands executed when selecting the menu item.\n var string onSelAction_S[MAX_SEL_ACTIONS]; // Arguments for commands specified in the onSelAction property.\n var string onChgSetOption; // Gothic.ini file parameter modified by this menu item.\n var string onChgSetOptionSection; // Section of the Gothic.ini file where the modified parameter is located.\n var func onEventAction[MAX_EVENTS]; // Call the required function by a constant identifier.\n var int posx; // Top-left point of the menu item on the screen horizontally (X-axis).\n var int posy; // Top-left point of the menu item on the screen vertically (Y-axis).\n var int dimx; // Width of the menu item in virtual coordinates.\n var int dimy; // Height of the menu item in virtual coordinates.\n var float sizeStartScale; // Initial size of the item. Not used.\n var int flags; // Flags of the menu item.\n var float openDelayTime; // Delay before opening the item. Not used.\n var float openDuration; // Opening time. Not used.\n var float userFloat[MAX_USERVARS]; // Digital settings of menu items.\n var string userString[MAX_USERVARS]; // String settings of menu items.\n var int frameSizeX; // Text offset inside the frame on the X-axis.\n var int frameSizeY; // Text offset inside the frame on the Y-axis.\n var string hideIfOptionSectionSet; // Section of Gothic.ini file where the option determining the display of this menu item is located.\n var string hideIfOptionSet; // Gothic.ini file parameter determining the display of this menu item.\n var int hideOnValue; // Value of the Gothic.ini file parameter at which this interface element is not displayed.\n}; \n
"},{"location":"zengin/scripts/classes/c_menuitem/#class-members","title":"Class members","text":"Property Type Description fontName string Font of the menu item. text string Text of the interface element. backPic string Background image of menu items. alphaMode string Transparency blending mode of menu items. alpha int Transparency of the menu item. type int Type of the interface element. onSelAction int Array of commands executed when selecting the menu item. onSelAction_S string Arguments for commands specified in the onSelAction property. onChgSetOption string Gothic.ini file parameter modified by this menu item. onChgSetOptionSection string Section of the Gothic.ini file where the modified parameter is located. onEventAction Func Call the required function by a constant identifier. posx int Top-left point of the menu item on the screen horizontally (X-axis). posy int Top-left point of the menu item on the screen vertically (Y-axis). dimx int Width of the menu item in virtual coordinates. dimy int Height of the menu item in virtual coordinates. sizeStartScale float Initial size of the item. Not used. flags int Flags of the menu item. openDelayTime float Delay before opening the item. Not used. openDuration float Opening time. Not used. userFloat float Digital settings of menu items. userString string String settings of menu items. frameSizeX int Text offset inside the frame on the X-axis. frameSizeY int Text offset inside the frame on the Y-axis. hideIfOptionSectionSet string Section of Gothic.ini file where the option determining the display of this menu item is located. hideIfOptionSet string Gothic.ini file parameter determining the display of this menu item. hideOnValue int Value of the Gothic.ini file parameter at which this interface element is not displayed."},{"location":"zengin/scripts/classes/c_menuitem/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_menuitem/#fontname","title":"fontName","text":"*.TGA
file defining the font of the displayed text of the menu item.
To create a color change effect, two fonts are needed:
The first font is specified in the fontName
field and is used by default. The second font with the suffix _Hi
is used to replace the text on the active (selected) element. This creates a highlighting effect.
"},{"location":"zengin/scripts/classes/c_menuitem/#text","title":"text","text":"Text inside a menu item.
Used to determine possible values \u200b\u200bfor game settings. See onChgSetOptionSection.
Also used to display hints about the item at the bottom of the menu when the MENU_SHOW_INFO
flag is set.
// Text displayed in the element\n\ntext[0] = \"New Game\";\n\n// Text in the interface element responsible for game settings\n// One of the presented options is displayed\n\ntext[0] = \"off|on\";\n\n// Tooltip for the selected element\n// Index 1 is used for tooltips, not 0\n\ntext[1] = \"Start a new adventure\";\n
"},{"location":"zengin/scripts/classes/c_menuitem/#backpic","title":"backPic","text":"Background image of the menu item in *.TGA
format.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n backpic = \"Inv_Slot_Highlighted.tga\";\n}\n
"},{"location":"zengin/scripts/classes/c_menuitem/#alphamode","title":"alphaMode","text":"Texture transparency blending mode. Used in conjunction with the alpha property. This parameter's value is ignored if the backPic property is not specified.
Supported modes:
MAT_DEFAULT
Uses the standard texture. If the material has an alpha channel, it will be transparent; otherwise, it will be opaque.
NONE
Transparency is not used unless the texture itself is transparent.
BLEND
Blends the alpha channel of the texture with the background.
ADD
Adds the alpha channel of the texture to the background.
SUB
Subtracts the alpha channel of the texture from the background.
MUL
and MUL2
Multiplies the alpha channel of the texture by the background.
"},{"location":"zengin/scripts/classes/c_menuitem/#alpha","title":"alpha","text":"Menu element transparency. Accepts values \u200b\u200bfrom 0 to 255. Without specifying the backPic property, the value of this parameter is ignored.
The alpha channel rendering mode is determined using the alphaMode property.
"},{"location":"zengin/scripts/classes/c_menuitem/#type","title":"type","text":"Interface element type. Some interface elements have their own settings determined by the userFloat and userString properties.
Constants for menu item types are described in the file Scripts/System/_intern/Menu.d
.
CONST INT MENU_ITEM_UNDEF = 0; // Undefined\nCONST INT MENU_ITEM_TEXT = 1; // Text\nCONST INT MENU_ITEM_SLIDER = 2; // Slider\nCONST INT MENU_ITEM_INPUT = 3; // Input field\nCONST INT MENU_ITEM_CURSOR = 4; \nCONST INT MENU_ITEM_CHOICEBOX = 5; // Checkbox\nCONST INT MENU_ITEM_BUTTON = 6; // Button\nCONST INT MENU_ITEM_LISTBOX = 7; // Frame\n
MENU_ITEM_UNDEF
Undefined element type. Not used in scripts.
MENU_ITEM_TEXT
Menu item type \"Text\". Text can be multiline by setting the IT_MULTILINE
flag.
MENU_ITEM_SLIDER
Menu item type \"Slider\". Additional settings are provided for the slider.
userFloat[0]
property determines the number of divisions for the slider. userFloat[1]
property determines the width of the slider. userString[0]
property determines the background image for the slider thumb. INSTANCE MENUITEM_AUDIO_MUSICVOL_SLIDER(C_MENU_ITEM_DEF)\n{\n backPic = MENU_SLIDER_BACK_PIC;\n type = MENU_ITEM_SLIDER; // Type: Slider\n // [...]\n onChgSetOption = \"musicVolume\"; // INI file parameter\n onChgSetOptionSection = \"SOUND\"; // INI file section\n userFloat[0] = 15; // Number of slider positions\n userString[0] = MENU_SLIDER_POS_PIC; // Background image of the slider\n // [...]\n};\n
MENU_ITEM_INPUT
This type of element is intended for entering control keys during configuration, as well as for entering the name of the save in the corresponding menu.
MENU_ITEM_CURSOR
Deprecated element type. Not used in scripts.
MENU_ITEM_CHOICEBOX
\"SELECT\" type allowing the selection of one of the available values.
MENU_ITEM_BUTTON
Button. Not used in scripts.
The userString[0]
property determines which image will be used for the disabled button. The backPic property is responsible for the background image of the enabled button. MENU_ITEM_LISTBOX
Menu item type used in the \"Quest Log\" menu.
The userString[0]
property determines which task list will be displayed in this element. userstring[0] = \"CURRENTMISSIONS\";\nuserstring[0] = \"OLDMISSIONS\";\nuserstring[0] = \"FAILEDMISSIONS\";\nuserstring[0] = \"LOG\";\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onselaction","title":"onSelAction","text":"Array of commands executed when selecting the menu item.
Each command receives parameters in the onSelAction_S
property.
Constants are described in the file Scripts/System/_intern/Menu.d
.
CONST INT SEL_ACTION_UNDEF = 0; // No action. Used when setting game parameters, calling functions...\nCONST INT SEL_ACTION_BACK = 1; // Return to the previous menu or game\nCONST INT SEL_ACTION_STARTMENU = 2; // Open a menu\nCONST INT SEL_ACTION_STARTITEM = 3; // Special command for save slots\nCONST INT SEL_ACTION_CLOSE = 4; // Close menu or game\nCONST INT SEL_ACTION_CONCOMMANDS = 5; // Execute console command\nCONST INT SEL_ACTION_PLAY_SOUND = 6; // Play sound from C_SFX instance\nCONST INT SEL_ACTION_EXECCOMMANDS = 7; // Execute command specified in the onSelAction_S field using RUN or EFFECT commands\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onselaction_s","title":"onSelAction_S","text":"Arguments for commands specified in the onSelAction
property.
Below are commands and their arguments:
SEL_ACTION_UNDEF
This command has no arguments and is mostly used in options and for calling script functions.
instance MENUITEM_MAIN_CREDITS(C_MENU_ITEM_DEF)\n{\n text[0] = \"Credits\";\n // [...]\n onselaction[0] = SEL_ACTION_UNDEF;\n oneventaction[1] = showcredits;\n};\n\nfunc int showcredits()\n{\n PlayVideo(\"credits.bik\");\n PlayVideo(\"credits2.bik\");\n return 1;\n};\n
SEL_ACTION_BACK
This command has no arguments. It returns to the previous menu or the game.
instance MENUITEM_MAIN_RESUME(C_MENU_ITEM_DEF)\n{\n text[0] = \"Resume\";\n text[1] = \"Resume the current game\";\n // [...]\n onselaction[0] = SEL_ACTION_BACK;\n};\n
SEL_ACTION_STARTMENU
The argument for this command is the menu instance. The specified menu will be displayed.
instance MENUITEM_MAIN_EXIT(C_MENU_ITEM_DEF)\n{\n text[0] = \"Quit Game\";\n text[1] = \"Leave the world of Gothic II\";\n onselaction[0] = SEL_ACTION_STARTMENU;\n onselaction_s[0] = \"MENU_LEAVE_GAME\";\n // [...]\n};\n\ninstance MENU_LEAVE_GAME(C_MENU_DEF)\n{\n // [...]\n};\n
SEL_ACTION_STARTITEM
The argument is an interface element serving as a slot for saving the game.
INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_STARTITEM;\n onSelAction_S[0]= \"MENUITEM_SAVE_SLOT1\";\n onSelAction[1] = SEL_ACTION_CLOSE;\n onSelAction_S[1]= \"SAVEGAME_SAVE\";\n};\n
SEL_ACTION_CLOSE
The closing menu command supports the following arguments:
NEW_GAME
Start a new game.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) \n{\n // [...]\n text[0] = \"New Game\";\n text[1] = \"Start a new adventure\";\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"NEW_GAME\";\n};\n
LEAVE_GAME
Exit the game.
INSTANCE MENUITEM_LEAVE_GAME_YES(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Yes.\";\n text[1] = \"Yes, I'll be back!\";\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"LEAVE_GAME\";\n};\n
SAVEGAME_SAVE
Save the game to the selected slot and return to the game.
INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_STARTITEM;\n onSelAction_S[0]= \"MENUITEM_SAVE_SLOT1\";\n onSelAction[1] = SEL_ACTION_CLOSE;\n onSelAction_S[1]= \"SAVEGAME_SAVE\";\n};\n
SAVEGAME_LOAD
Load the game from the selected slot and return to the game.
INSTANCE MENUITEM_LOAD_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"SAVEGAME_LOAD\";\n};\n
SEL_ACTION_CONCOMMANDS
The argument is a console commands.
INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[1] = SEL_ACTION_CONCOMMANDS;\n onSelAction_S[1]= \"goto pos 0 0 0\";\n};\n
SEL_ACTION_PLAY_SOUND
The argument is an C_SFX class instance.
INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[1] = SEL_ACTION_PLAY_SOUND;\n onSelAction_S[1]= \"LevelUp\";\n};\n
SEL_ACTION_EXECCOMMANDS
There are two supported executable commands: RUN
and EFFECTS
.
RUN
Indicates the instance of the menu element that is used to select the key.
INSTANCE MENU_ITEM_KEY_UP(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Forward\";\n text[1] = \"press DEL key to empty slot and RETURN to define\";\n onSelAction[0] = SEL_ACTION_EXECCOMMANDS;\n onSelAction_S[0]= \"RUN MENU_ITEM_INP_UP\";\n};\n\nINSTANCE MENU_ITEM_INP_UP(C_MENU_ITEM_DEF)\n{\n // [...]\n text[1] = \"Please press the desired key for this action.\";\n type = MENU_ITEM_INPUT;\n onChgSetOption = \"keyUp\";\n onChgSetOptionSection = \"KEYS\";\n};\n
EFFECTS
Specifies the menu item instance to which the focus switches.
INSTANCE MENU_ITEM_SEL_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n text[0] = \"Current\\nQuests\";\n // [...]\n onSelAction[0] = SEL_ACTION_EXECCOMMANDS;\n onSelAction_S[0]= \"EFFECTS MENU_ITEM_LIST_MISSIONS_ACT\"; \n};\n\ninstance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n type = MENU_ITEM_LISTBOX; \n text[0] = \"Act Missions\";\n // [...]\n userString[0] = \"CURRENTMISSIONS\"; \n};\n
There are also two commands, SETDEFAULT
and SETALTERNATIVE
, which set control settings. The first restores default settings, and the second uses alternative character control settings.
"},{"location":"zengin/scripts/classes/c_menuitem/#onchgsetoption","title":"onChgSetOption","text":"Parameter of the Gothic.ini
file that will be modified by this menu item.
instance MENUITEM_GAME_FIGHTFOCUS_CHOICE(C_MENU_ITEM_DEF)\n{\n text[0] = \"none|box|lighten|both\";\n // [...]\n onChgSetOption = \"highlightMeleeFocus\"; // INI parameter\n onChgSetOptionSection = \"GAME\"; // INI section\n // [...]\n};\n
The text[0]
property of such an element usually specifies possible values of the modified parameter. Values are listed using the |
symbol.
Make sure that the number of parameter options in the menu corresponds to the number of options in the Gothic.ini
file.
highlightMeleeFocus=2\n; ... here you can turn on an optional focus highlight effect during fighting\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onchgsetoptionsection","title":"onChgSetOptionSection","text":"The section of the Gothic.ini file in which the parameter being changed is located.
See onChgSetOption above.
"},{"location":"zengin/scripts/classes/c_menuitem/#oneventaction","title":"onEventAction","text":"Allows a user to call a function on a specified event.
The list of constants is described in the file Scripts/System/_intern/Menu.d
.
const int EVENT_UNDEF = 0; // Undefined\nconst int EVENT_EXECUTE = 1; // Process start event\nconst int EVENT_CHANGED = 2; // Menu parameter change event\nconst int EVENT_LEAVE = 3; // Menu item focus loss event\nconst int EVENT_TIMER = 4; // Timer fire event\nconst int EVENT_CLOSE = 5; // Menu close event\nconst int EVENT_INIT = 6; // Initialization event\nconst int EVENT_SEL_PREV = 7; // Select event of the previous menu item\nconst int EVENT_SEL_NEXT = 8; // Select event of the next menu item\n
For example, you can use the function associated with the constant EVENT_EXECUTE
to call a script function.
instance MENUITEM_MAIN_INTRO(C_MENU_ITEM_DEF) \n{\n text[0] = \"Play Intro\";\n text[1] = \"Play introduction sequence\";\n // [...]\n onEventAction[EVENT_EXECUTE] = ShowIntro;\n};\n\nfunc int ShowIntro()\n{\n PlayVideo(\"intro.bik\");\n return 1;\n};\n
"},{"location":"zengin/scripts/classes/c_menuitem/#posx","title":"posx","text":"The horizontal position of the top left point of the menu on the screen, measured in virtual coordinates.
Virtual coordinates
Virtual coordinates divide the menu into 8192 parts (0 - 8191
) horizontally and vertically. The position of the menu item is calculated based on these values.
"},{"location":"zengin/scripts/classes/c_menuitem/#posy","title":"posy","text":"The vertical position of the top left point of the menu on the screen, measured in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menuitem/#dimx","title":"dimx","text":"The width of the menu item in virtual coordinates.
Tip
To automatically determine the width, enter -1
. In this case, the width is calculated based on the text contained in the element.
"},{"location":"zengin/scripts/classes/c_menuitem/#dimy","title":"dimy","text":"The height of the menu item in virtual coordinates.
Tip
To automatically determine the element's height, enter a value of -1
. In this case, the height is calculated taking into account the text contained in the element.
"},{"location":"zengin/scripts/classes/c_menuitem/#sizestartscale","title":"sizeStartScale","text":"Deprecated setting
Size of the menu item at the beginning.
"},{"location":"zengin/scripts/classes/c_menuitem/#flags","title":"flags","text":"Flags of the menu item.
Constants for all flags are described in the file Scripts/System/_intern/Menu.d
.
const int IT_CHROMAKEYED = 1;\nconst int IT_TRANSPARENT = 2;\nconst int IT_SELECTABLE = 4; // Element can be selected\nconst int IT_MOVEABLE = 8;\nconst int IT_TXT_CENTER = 16; // Align text to center\nconst int IT_DISABLED = 32; // Interactive item\nconst int IT_FADE = 64;\nconst int IT_EFFECTS_NEXT = 128; // Flag for influencing an adjacent menu item\nconst int IT_ONLY_OUT_GAME = 256; // Element available only outside the game\nconst int IT_ONLY_IN_GAME = 512; // Element available only in-game\nconst int IT_PERF_OPTION = 1 << 10; // Option responsible for performance\nconst int IT_MULTILINE = 1 << 11; // Multi-line text element\nconst int IT_NEEDS_APPLY = 1 << 12; // Need to apply a settings. Used when changing screen resolution\nconst int IT_NEEDS_RESTART = 1 << 13; // The game need to be restarted\nconst int IT_EXTENDED_MENU = 1 << 14; // Advanced menu flag\n
IT_CHROMAKEYED
Empty flag. Not used.
IT_TRANSPARENT
Empty flag. Not used.
IT_SELECTABLE
Items marked with this flag can be selected.
IT_MOVEABLE
Empty flag. Not used.
Intended use In early engine versions, the initial position of the element could be specified using the startPosX
and startPosY
properties. The element moved from these coordinates to the desired position.
At the beginning of the video below, it can be seen that the elements slides into the screen. That was probably done using this flag and mentioned parameters.
IT_TXT_CENTER
Aligns the text in the element to the center.
IT_DISABLED
The menu item becomes inactive.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n text[0] = \"New Game\";\n text[1] = \"Start a new adventure\";\n flags = flags | IT_TXT_CENTER | IT_DISABLED;\n // [...]\n};\n
IT_FADE
Empty flag. Not used.
IT_EFFECTS_NEXT
This flag affects the next neighboring element, i.e., the element specified in the items
list of the C_MENU
class.
instance MENU_OPT_GAME(C_MENU_DEF)\n{\n // [...]\n items[1] = \"MENUITEM_GAME_SUB_TITLES\";\n items[2] = \"MENUITEM_GAME_SUB_TITLES_CHOICE\";\n // [...]\n};\n
In this case, the element affecting (MENUITEM_GAME_SUB_TITLES_CHOICE) is usually made non-selectable.
instance MENUITEM_GAME_SUB_TITLES(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Subtitles\";\n text[1] = \"Subtitles on/off\";\n flags = flags | IT_EFFECTS_NEXT;\n // [...]\n};\n\ninstance MENUITEM_GAME_SUB_TITLES_CHOICE(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"no|yes\";\n flags = flags & ~IT_SELECTABLE;\n // [...]\n};\n
This flag is mainly used for options and for managing checkboxes, sliders, and enumerations.
IT_ONLY_OUT_GAME
This flag determines that the menu item is only available before starting the game. Once you start the game, the menu item becomes unavailable.
IT_ONLY_IN_GAME
This flag determines that the menu item is only available in the running game. Until the game is started, the element remains unavailable.
IT_PERF_OPTION
A special flag for options. Settings affecting the game's performance are marked with this flag.
IT_MULTILINE
Flag for multiline text. The text of such elements can be moved to a new line using the newline escape sequence \\n
.
IT_NEEDS_APPLY
Flag indicating the need to apply settings. Used when changing the game resolution.
IT_NEEDS_RESTART
Flag indicating that the game needs to be restarted for the settings to take effect.
IT_EXTENDED_MENU
Flag indicating that this element is part of the \"Extended Menu.\" It is displayed only if the extendedMenu
parameter in the Gothic.ini
file is set to 1
.
"},{"location":"zengin/scripts/classes/c_menuitem/#opendelaytime","title":"openDelayTime","text":"Deprecated setting
Delay before opening a menu item.
"},{"location":"zengin/scripts/classes/c_menuitem/#openduration","title":"openDuration","text":"Deprecated setting
The time the menu item was opened.
"},{"location":"zengin/scripts/classes/c_menuitem/#userfloat","title":"userFloat","text":"Numerical settings of the interface element. Depending on the interface element, the purpose of the property changes. See type.
"},{"location":"zengin/scripts/classes/c_menuitem/#userstring","title":"userString","text":"String settings of the interface element. The purpose of the property changes depending on the interface element. See type`.
"},{"location":"zengin/scripts/classes/c_menuitem/#framesizex","title":"frameSizeX","text":"Indentation of text inside the frame along the X axis. This applies the padding to both sides of the frame. Measured in virtual coordinates from 0 to 4095.
Frames are a special tool designed to work with the log of tasks and quests.
Used for elements of type MENU_ITEM_LISTBOX
.
instance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n backpic = \"NW_Misc_CaveWall_01.tga\";\n type = MENU_ITEM_LISTBOX;\n text[0] = \"Act Missions\";\n // [...]\n userstring[0] = \"CURRENTMISSIONS\";\n framesizex = 2000;\n framesizey = 2000;\n};\n
As a result, we get the following frame (Source: Gothic-Library):
And the width and height of the frame are set, as for all elements, by the dimx and dimy properties.
"},{"location":"zengin/scripts/classes/c_menuitem/#framesizey","title":"frameSizeY","text":"Indentation of text inside the frame along the Y axis. In this case, the indentation is applied at the top and bottom of the frame. Measured in virtual coordinates from 0 to 4095.
See frameSizeX above.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideifoptionsectionset","title":"hideIfOptionSectionSet","text":"The section of the Gothic.ini
file with the option which value of determines the display of this menu item.
This property works together with the hideIfOptionSet
and hideOnValue
properties.
In the example below, the interface element will not be displayed until the useGothic1Controls
parameter in the GAME section is set to 1, i.e., enabled.
instance MENU_ITEM_NEXTMENU(C_MENU_ITEM_DEF)\n{\n text[0] = \"More keys...\";\n text[1] = \"Configure further control keys\";\n // [...]\n hideifoptionsectionset = \"GAME\";\n hideifoptionset = \"useGothic1Controls\";\n hideonvalue = 1;\n};\n
Tip
Gothic.ini
settings can also be changed through the main menu. See onChgSetOption
and onChgSetOptionSection
.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideifoptionset","title":"hideIfOptionSet","text":"The Gothic.ini
file parameter, the value of which determines the display of this menu item.
See hideIfOptionSectionSet.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideonvalue","title":"hideOnValue","text":"The value of the Gothic.ini
file parameter at which this interface element is not displayed.
See hideIfOptionSectionSet.
"},{"location":"zengin/scripts/classes/c_menuitem/#predefined-instances","title":"Predefined instances","text":"There are a lot of predefined class instances in the menu C_MENU_ITEM
performing a strictly defined function. They cannot be renamed, but they can be configured to a certain extent.
Instance Description MENUITEM_LOADSAVE_THUMBPIC Save picture in the Save/Load menu. MENUITEM_LOADSAVE_LEVELNAME_VALUE The name of the level of the selected Save/Load menu item. MENUITEM_LOADSAVE_DATETIME_VALUE The date the selected Save/Load menu item was saved. MENUITEM_LOADSAVE_GAMETIME_VALUE Game time for saving the selected Save/Load menu item. MENUITEM_LOADSAVE_PLAYTIME_VALUE Total play time of the selected Save/Load menu item. MENUITEM_SAVE_SLOT1 - MENUITEM_SAVE_SLOT20 Save menu slots. MENUITEM_LOAD_SLOT1 - MENUITEM_LOAD_SLOT20 Load menu slots. MENU_ITEM_LIST_MISSIONS_ACT Frame with a list of current tasks in the journal. MENU_ITEM_LIST_MISSIONS_FAILED Frame with a list of failed tasks in the log. MENU_ITEM_LIST_MISSIONS_OLD Frame with a list of old tasks in the journal. MENU_ITEM_LIST_LOG Frame of general information in the task log. MENU_ITEM_CONTENT_VIEWER Job log window. MENU_ITEM_DAY Current day in the quest log window. MENU_ITEM_TIME Current time in the task log window. MENU_ITEM_PLAYERGUILD Character's guild in the statistics window. MENU_ITEM_TALENT_0_TITLE - MENU_ITEM_TALENT_16_TITLE The name of the character's talent. Array indexes are used TXT_TALENTS
from the Text.d
file. There may be more elements, depending on the talents realized in the game. MENU_ITEM_TALENT_0_SKILL - MENU_ITEM_TALENT_16_SKILL Character's talent level. Array indexes are used TXT_TALENTS_SKILLS
from the Text.d
file. MENU_ITEM_EXP The character's current experience value in the statistics window. MENU_ITEM_LEVEL Current character level in the statistics window. MENU_ITEM_LEVEL_NEXT The amount of experience required to obtain the next level in the statistics window. MENU_ITEM_LEARN The number of available training points in the statistics window. MENU_ITEM_ATTRIBUTE_1 - MENU_ITEM_ATTRIBUTE_4 Character attributes in the statistics window. MENU_ITEM_ARMOR_1 - MENU_ITEM_ARMOR_4 Character protection in the statistics window."},{"location":"zengin/scripts/classes/c_musicsys_cfg/","title":"C_MUSICSYS_CFG Daedalus class","text":""},{"location":"zengin/scripts/classes/c_musicsys_cfg/#c_musicsys_cfg-daedalus-class","title":"C_MUSICSYS_CFG Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_MusicSys_CFG
defines the global settings for the game's music.
An instance of this class is declared only once.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Music.d
script file.
C_MusicSys_CFG Daedalus class class C_MusicSys_CFG\n{\n var float volume; // Music volume\n var int bitResolution; // Sound quality\n var int globalReverbEnabled; // Enable global reverb\n var int sampleRate; // Frequency\n var int numChannels; // Sound channels\n var int reverbBufferSize; // Reverb buffer size\n};\n
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-members","title":"Class members","text":"Variable Type Description volume float Overall game music volume bitResolution int Sound quality globalReverbEnabled int Enable global reverb sampleRate int Frequency numChannels int Number of sound chanells reverbBufferSize int The size of reverb buffer"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#volume","title":"volume","text":"The overall volume of the background music (soundtrack). From 0.0 to 1.0.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#bitresolution","title":"bitResolution","text":"Sound quality. 8 or 16 bit.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#globalreverbenabled","title":"globalReverbEnabled","text":"Enable global reverb.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#samplerate","title":"sampleRate","text":"Frequency. From 11050 to 44100.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#numchannels","title":"numChannels","text":"Number of sound channels. From 16 to 32.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#reverbbuffersize","title":"reverbBufferSize","text":"The size of the reverb buffer.
"},{"location":"zengin/scripts/classes/c_musictheme/","title":"C_MUSICTHEME Daedalus class","text":""},{"location":"zengin/scripts/classes/c_musictheme/#c_musictheme-daedalus-class","title":"C_MUSICTHEME Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_MusicTheme
describes musical themes.
"},{"location":"zengin/scripts/classes/c_musictheme/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Music.d
script file.
C_MusicTheme Daedalus class class C_MusicTheme\n{\n var string file; // Sound file in DirectMusic `.sgt` format\n var float vol; // Sound volume\n var int loop; // Enable cycle\n var float reverbMix; // Reverb mixing\n var float reverbTime; // Reverb time\n var int transType; // Type of transition to the next theme\n var int transSubType; // Subtype of transition to the next theme song\n};\n
"},{"location":"zengin/scripts/classes/c_musictheme/#class-members","title":"Class members","text":"Variable Type Description file string Sound file in DirectMusic .sgt
format vol float Sound volume loop int Enable/disable cycle reverbMix float Reverb mixing reverbTime float Reverb time transType int The type of transition to the next theme song transSubType int The subtype of transition to the next theme song"},{"location":"zengin/scripts/classes/c_musictheme/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_musictheme/#file","title":"file","text":"DirectMusic sound in *.sgt format or MIDI file.
"},{"location":"zengin/scripts/classes/c_musictheme/#vol","title":"vol","text":"The volume of the theme song. From 0.0 to 1.0.
"},{"location":"zengin/scripts/classes/c_musictheme/#loop","title":"loop","text":"Enable/disable theme music looping. Disabled = 0. Enabled = 1.
"},{"location":"zengin/scripts/classes/c_musictheme/#reverbmix","title":"reverbMix","text":"Reverb mixing. Measured in decibels.
"},{"location":"zengin/scripts/classes/c_musictheme/#reverbtime","title":"reverbTime","text":"Reverberation time in milliseconds.
"},{"location":"zengin/scripts/classes/c_musictheme/#transtype","title":"transType","text":"The type of transition to the next theme song.
The list of constants for all transitions types is described in the file Scripts/System/_intern/Music.d
const int TRANSITION_TYPE_NONE = 1; // No transition\nconst int TRANSITION_TYPE_GROOVE = 2; // Ripple\nconst int TRANSITION_TYPE_FILL = 3; // Padding\nconst int TRANSITION_TYPE_BREAK = 4; // Break\nconst int TRANSITION_TYPE_INTRO = 5; // Introductory\nconst int TRANSITION_TYPE_END = 6; // End topic\nconst int TRANSITION_TYPE_ENDANDINTRO = 7; // End and start new\n
"},{"location":"zengin/scripts/classes/c_musictheme/#transsubtype","title":"transSubType","text":"The subtype of transition to the next theme song.
The list of constants for all transitions subtypes is described in the file Scripts/System/_intern/Music.d
const INT TRANSITION_SUB_TYPE_IMMEDIATE = 1; // Instant transition\nconst INT TRANSITION_SUB_TYPE_BEAT = 2; // Rhythmic transition\nconst INT TRANSITION_SUB_TYPE_MEASURE = 3; // Gradual transition\n
"},{"location":"zengin/scripts/classes/c_musictheme/#name-features","title":"Name features","text":"The musical themes of the game are played depending on the game situation. By default, the theme with the _STD
(standard) suffix is played. In case of a threat, the _THR
(threat) theme will be played. During the combat the _FGT
(fight) theme plays.
Danger
Make sure that you use proper naming convention for MusicThemes and oCZoneMusic
vobs. The theme with OC_
prefix will play in a zone with name like OLDCAMP_OC
or any other ending with _OC
instance WOO_DAY_STD(C_MUSICTHEME_STANDARD)\n{\n file = \"woo_daystd.sgt\";\n};\n\ninstance WOO_DAY_THR(C_MUSICTHEME_THREAT)\n{\n file = \"woo_daythr.sgt\";\n};\n\ninstance WOO_DAY_FGT(C_MUSICTHEME_FIGHT)\n{\n file = \"woo_dayfgt.sgt\";\n};\n
In addition, the suffix _DAY_
and _NGT_
determines whether the theme should be played on day or night. instance OWD_DAY_FGT(C_MUSICTHEME_FIGHT)\n{\n file = \"owp_dayfgt.sgt\";\n};\n\ninstance OWD_NGT_STD(C_MUSICTHEME_STANDARD)\n{\n file = \"owd_daystd.sgt\";\n};\n
Tip
In G2 the C_MUSICTHEME_STANDARD
, C_MUSICTHEME_THREAT
and C_MUSICTHEME_FIGHT
prototypes are used by default.
"},{"location":"zengin/scripts/classes/c_svm/","title":"C_SVM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_svm/#c_svm-daedalus-class","title":"C_SVM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
The C_SVM
class is used to define sound dialogues (smalltalk, reactions) that are defined for every C_NPC.voice.
"},{"location":"zengin/scripts/classes/c_svm/#class-definition","title":"Class definition","text":"C_SVM
class is the only class with variable number of members. The C_SVM
definition in the scripts dictates the content of the class. Every Gothic game has a different number of SVM entries. As an interesting information (more than anything else) we include a table with the numbers of voice lines and voices below.
Game voice lines voices Gothic 1 136 17 Gothic Sequel 110 17 (30 planned) Gothic 2 202 19 Gothic 2 Addon 235 19 Chronicles of Myrtana 1346 73 Returning New Balance 495 19"},{"location":"zengin/scripts/classes/c_svm/#rules","title":"Rules","text":"The number of instances is defined by a constant integer with a specified name read by the engine.
const int SVM_MODULES = 18;\n
Info
The value SVM_MODULES = 18
means 18 SVMs will be parsed by the engine and because the first one, SVM_0
, is empty, the final number of voices is 18 - 1 = 17.
Instances of the C_SVM
class must have the name SVM_XXX
.
instance svm_1(c_svm)\n{\n // ...\n};\n
The first instance svm_0
is always empty, it is used internally by the engine. instance svm_0(c_svm) {};\n
"},{"location":"zengin/scripts/classes/c_svm/#usage-in-the-scripts","title":"Usage in the scripts","text":"While some defined SVMs are used automatically by the engine - the 20 smalltalk lines for example, others are used in the scripts. To instruct the engine to run a specific SVM, external function AI_OutputSVM
is used. In the original scripts it is wrapped in a script function B_Say. To reference the SVM, you use the $
symbol followed by the name of the member variable in the C_SVM
class definition.
// some code\n {\n PrintScreen (\"Not enough skill points!\", -1,-1,\"FONT_OLD_20_WHITE.TGA\",1);\n B_Say (self, other, \"$NOLEARNNOPOINTS\");\n };\n// some code\n
Here the $NOLEARNNOPOINTS
references the var string NoLearnNoPoints
in SVM.D. The voice is then chosen automatically by the engine. class C_SVM\n{\n //...\n\n // Teacher comments\n var string NoLearnNoPoints; // NPC teacher doesn't teach - not enough learning points!\n var string NoLearnOverMax; // NPC teacher doesn't teach - cannot teach above 100 points!\n var string NoLearnYouAlreadyKnow; // You have to know something to become a master!\n var string NoLearnYoureBetter; // You are better than the teacher!\n\n //...\n};\n
"},{"location":"zengin/scripts/extenders/","title":"Daedalus extenders","text":""},{"location":"zengin/scripts/extenders/#daedalus-extenders","title":"Daedalus extenders","text":"The default scripting language Daedalus can be quite limiting. Over the years the community created quite a few extenders to, well, extend the functionality. Before Union came along, the standard to interface with the engine was the script library Ikarus and a collection of packages LeGo built on top of that. Not so recently, an additional script packet was made (and is actively being worked on) AF Script Packet that offers even more functionality and is built on top of Ikarus & LeGo. With the adoption of Union and plugins the Union system can use a new extender emerged called zParserExtender. Other Union plugins can, of course, implement their own external functions. A lot of scripts are also scattered on the Gothic forums, and documentation of some of them can be found in the Standalone section.
"},{"location":"zengin/scripts/extenders/afsp/","title":"AF Script Packet","text":""},{"location":"zengin/scripts/extenders/afsp/#af-script-packet","title":"AF Script Packet","text":"Auronen & Fawkes' Script Packet is a script package built on top of Ikarus and LeGo. It implements many features and there is also a Union version which is in its infancy stage.
Note
AFSP's documentation is lacking (@Auronen: \"My fault\"). The authors will host the documentation on GMC.
Contacts Authors Fawkes & Auronen GitHub AFSP Forum AFSP"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/","title":"Enhanced Information Manager","text":""},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#enhanced-information-manager","title":"Enhanced Information Manager","text":"Warning
This is a quick paste-in of and old version of AFSP's documentation and the information should be taken with a grain of salt. It may not be up-to-date since AFSP is being developed all the time and this is only a demo page.
Enhanced Information Manager allows you to more precisely control the Information Manager (dialogue manager). Change color, font and much more! This package \"scans\" the dialogue string for modifiers and alters the string based on the modifiers you specify.
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#initialization","title":"Initialization","text":"To use this feature you have to:
Add _headers_G[1/2]_EnhancedInfoManager.src
or _headers_G[1/2]_All.src
to your Gothic.src
after Ikarus and LeGo initialization. Call G12_EnhancedInfoManager_Init();
from your INIT_GLOBAL()
function in Startup.d
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-colour","title":"Change colour","text":"Set font color for a dialogue choice.
h@[hex color value]\n
Set font color for highlighted dialogue choice. hs@[hex color value]\n
Exampledescription = \"h@2a85a3 hs@2ea9d1 This dialogue is blue.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-font","title":"Change font","text":"Set font itself for a dialogue choice.
f@[font name]\n
Set font itself for highlighted dialogue choice. fs@[font name]\n
Exampledescription = \"f@font_old_20_white.tga fs@font_old_10_white.tga This dialogue has a different font, when selected.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-text-alignment","title":"Change text alignment","text":"Align text left.
al@\n
Align text center. ac@\n
Align text right. ar@\n
Exampledescription = \"al@ This dialogue has LEFT alignment.\";\ndescription = \"ac@ This dialogue has CENTER alignment.\";\ndescription = \"ar@ This dialogue has RIGHT alignment.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#disable-dialogue","title":"Disable dialogue","text":"Player cannot highlight (and select) this dialogue.
d@\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#text-input-field","title":"Text input field","text":"Input field allows you to turn a dialogue choice into an input text field.
a@\n
ExampleINSTANCE DIA_Xardas_Password (C_Info)\n{\n npc = NONE_100_Xardas;\n nr = 1;\n condition = DIA_Xardas_Password_Condition;\n information = DIA_Xardas_Password_Info;\n permanent = FALSE;\n description = \"a@ What is the password to get to the Mages of Water?\";\n};\n\nFUNC INT DIA_Xardas_Password_Condition () {\n return TRUE;\n};\n\nFUNC VOID DIA_Xardas_Password_Info () {\n if (Hlp_StrCmp (InfoManagerAnswer, \"TETRIANDOCH\"))\n {\n PrintScreen (\"Yes that is correct!\", -1, -1, \"font_old_10_white.tga\", 3);\n }\n else\n {\n PrintScreen (\"No that is wrong!\", -1, -1, \"font_old_10_white.tga\", 3);\n };\n};\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#dialogue-numbers","title":"Dialogue numbers","text":"This feature shows a dialogue number next to the dialogue line (visual for Dialogue keyboard controls). To turn this on you just set InfoManagerNumKeysNumbers
variable to true. (in your INIT_GLOBAL()
function).
InfoManagerNumKeysNumbers = TRUE;\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#dialogue-keyboard-controls","title":"Dialogue keyboard controls","text":"Note
This has also been fixed in Union and we noticed a strange behavior with different keyboard layouts.
This feature changes the way number keys affect dialogue selection. The first dialogue is no longer 0 and you highlight the dialogue option by pressing appropriate number.
InfoManagerNumKeysControls = TRUE;\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#spinners","title":"Spinners","text":"This is by far the most flashy feature of EIM as it allows you to use left/right arrow keys on a dialogue option to increase/decease numerical value. This can be used in many ways.
This feature is a bit more complex:
Set up a standard dialogue
Notice
Notice we are using \"dummy\" as a description, since it is going to get updated. If something goes wrong the \"dummy\" string shows up and you can clearly tell something went wrong.
INSTANCE PC_Pan_Cook_Meat (C_Info)\n{\n nr = 1;\n condition = PC_Pan_Cook_Meat_Condition;\n information = PC_Pan_Cook_Meat_Info;\n permanent = TRUE;\n description = \"dummy\"; //Description is updated in PC_Pan_Cook_Meat_Condition\n};\n
Most of the magic takes place in the condition function (apart from the code behind the scenes, of course).
var int selectedMeat; // global variable for this spinner value\n\nFUNC INT PC_Pan_Cook_Meat_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n var string lastSpinnerID;\n\n var int total; total = NPC_HasItems (self, ItFoMuttonRaw);\n\n if (selectedMeat == 0) { selectedMeat = 1; }; //Default initial value\n\n //Check currently selected spinned ID --> is it this one?\n if (Hlp_StrCmp (InfoManagerSpinnerID, \"CookMeat\"))\n {\n //Setup spinner if spinner ID has changed\n if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID))\n {\n //Restore previous value\n InfoManagerSpinnerValue = selectedMeat;\n };\n\n //Page Up/Down quantity\n InfoManagerSpinnerPageSize = 5;\n\n //Min/Max value (Home/End keys)\n InfoManagerSpinnerValueMin = 1;\n InfoManagerSpinnerValueMax = total;\n\n //Update number which is shown in description (in case it was changed by _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT\n selectedMeat = InfoManagerSpinnerValue;\n\n };\n\n lastSpinnerID = InfoManagerSpinnerID; //Remember last active spinner ID\n\n var string newDescription;\n\n //Spinner ID 'CookMeat'\n newDescription = \"s@CookMeat Cook some meat: \";\n\n newDescription = ConcatStrings (newDescription, IntToString (selectedMeat));\n newDescription = ConcatStrings (newDescription, \" / \");\n newDescription = ConcatStrings (newDescription, IntToString (total));\n\n //Update description\n PC_Pan_Cook_Meat.description = newDescription;\n return TRUE;\n };\n\n return FALSE;\n};\n
We can use the spinner value stored in selectedMeat
variable here in the info function to create the meat (or do other stuff with it).
FUNC VOID PC_Pan_Cook_Meat_Info () {\n //If we don't have any meat ... don't cook any :)\n if (!NPC_HasItems (self, ItFoMuttonRaw)) { return; };\n\n //This should not happen - but you never know!\n if (selectedMeat < 1) { return; };\n\n //This should not happen either! but just in case\n if (selectedMeat > (NPC_HasItems (self, ItFoMuttonRaw))) {\n selectedMeat = NPC_HasItems (self, ItFoMuttonRaw);\n };\n\n NPC_RemoveInvItems (self, ItFoMuttonRaw, selectedMeat);\n CreateInvItems (self, ItFoMutton, selectedMeat);\n\n //Reset value for next time\n selectedMeat = 1;\n};\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#spinners-full-code-example","title":"Spinners: Full code example","text":"Spinner example INSTANCE PC_Pan_Cook_Meat (C_Info)\n{\n nr = 1;\n condition = PC_Pan_Cook_Meat_Condition;\n information = PC_Pan_Cook_Meat_Info;\n permanent = TRUE;\n description = \"dummy\"; //Description is updated in PC_Pan_Cook_Meat_Condition\n};\n\nvar int selectedMeat;\n\nFUNC INT PC_Pan_Cook_Meat_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n var string lastSpinnerID;\n\n var int total; total = NPC_HasItems (self, ItFoMuttonRaw);\n\n if (selectedMeat == 0) { selectedMeat = 1; }; //Default initial value\n\n //Check currently selected spinned ID --> is it this one?\n if (Hlp_StrCmp (InfoManagerSpinnerID, \"CookMeat\"))\n {\n //Setup spinner if spinner ID has changed\n if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID))\n {\n //Restore previous value\n InfoManagerSpinnerValue = selectedMeat;\n };\n\n //Page Up/Down quantity\n InfoManagerSpinnerPageSize = 5;\n\n //Min/Max value (Home/End keys)\n InfoManagerSpinnerValueMin = 1;\n InfoManagerSpinnerValueMax = total;\n\n //Update number which is shown in description (in case it was changed by _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT\n selectedMeat = InfoManagerSpinnerValue;\n };\n\n lastSpinnerID = InfoManagerSpinnerID; //Remember last active spinner ID\n\n var string newDescription;\n\n //Spinner ID 'CookMeat'\n newDescription = \"s@CookMeat Cook some meat: \";\n\n newDescription = ConcatStrings (newDescription, IntToString (selectedMeat));\n newDescription = ConcatStrings (newDescription, \" / \");\n newDescription = ConcatStrings (newDescription, IntToString (total));\n\n //Update description\n PC_Pan_Cook_Meat.description = newDescription;\n return TRUE;\n };\n\n return FALSE;\n};\n\nFUNC VOID PC_Pan_Cook_Meat_Info ()\n{\n //If we don't have any meat ... don't cook any :)\n if (!NPC_HasItems (self, ItFoMuttonRaw)) { return; };\n\n //This should not happen - but you never know!\n if (selectedMeat < 1) { return; };\n\n //This should not happen either! but just in case\n if (selectedMeat > (NPC_HasItems (self, ItFoMuttonRaw)))\n {\n selectedMeat = NPC_HasItems (self, ItFoMuttonRaw);\n };\n\n NPC_RemoveInvItems (self, ItFoMuttonRaw, selectedMeat);\n CreateInvItems (self, ItFoMutton, selectedMeat);\n\n //Reset value for next time\n InfoManagerSpinnerValue = 1;\n};\n\nINSTANCE PC_Pan_Cook_Meat_Exit (C_Info)\n{\n nr = 999;\n condition = PC_Pan_Cook_Meat_Exit_Condition;\n information = PC_Pan_Cook_Meat_Exit_Info;\n permanent = TRUE;\n description = \"End\";\n};\n\nFUNC INT PC_Pan_Cook_Meat_Exit_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n return TRUE;\n };\n return FALSE;\n};\n\nFUNC VOID PC_Pan_Cook_Meat_Exit_Info ()\n{\n if (PLAYER_MOBSI_PRODUCTION != MOBSI_DIALOG_NONE)\n {\n PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_NONE;\n hero.aivar[AIV_INVINCIBLE] = FALSE;\n AI_StopProcessInfos (hero);\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/","title":"Ikarus","text":""},{"location":"zengin/scripts/extenders/ikarus/#ikarus","title":"Ikarus","text":"Ikarus is a Daedalus library for Gothic. It exploits the interpreter to allow arbitrary memory access and defines tonne of useful functions for interfacing with the engine.
Contacts Author Sektenspinner & contributors GitHub Ikarus Forum Ikarus Author Note (by Sektenspinner)
This script package is not called Ikarus for nothing:
One can leave the boundaries of Daedalus behind, but may also crash and burn. For instance, reading from invalid addresses won't trigger a zSpy warning but will result in a desktop crash with an Access Violation. This is not a reason to panic but requires a tolerance for frustration (which can be useful for scripters in general).
Of course, such spectacular-looking errors can be fixed, and with focused and systematic work, something sensible can be achieved.
In short: Extra care is needed! A bug that leads to a crash is not something you want in the release version. But if you work cleanly and test extensively, it's not such a big deal.
A good friend in debugging crashes is undoubtedly PrintDebug
. It allows sending messages to zSpy (for example, to narrow down where the crash is occurring). It's worth enabling debug messages by MEM_SetShowDebug
and the text filter (Options -> Textfilter) in zSpy.
Note
Ikarus is hosted on GitHub and the documentation is built in. The translation is planned.
"},{"location":"zengin/scripts/extenders/ikarus/constants/","title":"Ikarus User Constants","text":""},{"location":"zengin/scripts/extenders/ikarus/constants/#ikarus-user-constants","title":"Ikarus User Constants","text":"In the Constants file, you'll find user variables that control various aspects, including the debug output of Ikarus. You can customize these variables to suit your needs.
"},{"location":"zengin/scripts/extenders/ikarus/constants/#mem-helper","title":"MEM-Helper","text":" const string MEM_FARFARAWAY
Waypoint where the Mem-Helper is spawned (default: \"TOT\"
) const string MEM_HELPER_NAME
Name of the Mem-Helper (default: \"MEMHLP\"
) "},{"location":"zengin/scripts/extenders/ikarus/constants/#debug","title":"Debug","text":" const int zERR_ErrorBoxOnlyForFirst
Controls whether only the first error should trigger an error box (default: 1
). const int zERR_StackTraceOnlyForFirst
Determines if stack traces should be displayed only for the first error (default: 0
). "},{"location":"zengin/scripts/extenders/ikarus/constants/#mem_debug","title":"MEM_Debug","text":"The MEM_Debug
function allows you to set up a custom message channel for debugging purposes. You can adjust the following variables to configure this channel:
const string zERR_DEBUG_PREFIX
Specifies a prefix to be added to each debug message (default: \"Debug: \"
). const int zERR_DEBUG_TOSPY
Controls whether MEM_Debug
messages should be sent to zSpy (default: 1
). const int zERR_DEBUG_TYPE
Specifies the message type for MEM_Debug
messages when sent to zSpy (default: zERR_TYPE_INFO
). const int zERR_DEBUG_TOSCREEN
Determines whether MEM_Debug
messages should be printed to the screen (default: 0
). const int zERR_DEBUG_ERRORBOX
Allows you to display an error box for MEM_Debug
messages (default: 0
). "},{"location":"zengin/scripts/extenders/ikarus/constants/#error-message-types","title":"Error message types","text":"const int zERR_TYPE_OK = 0; /* [ungenutzt] */\nconst int zERR_TYPE_INFO = 1; /* MEM_Info */\nconst int zERR_TYPE_WARN = 2; /* MEM_Warn */\nconst int zERR_TYPE_FAULT = 3; /* MEM_Error */\nconst int zERR_TYPE_FATAL = 4; /* [ungenutzt] */\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/","title":"Ikarus examples","text":""},{"location":"zengin/scripts/extenders/ikarus/examples/#ikarus-examples","title":"Ikarus examples","text":"A collection of examples ported from the original Ikarus documentation.
Note
The original Ikarus documentation is a part of the code. You can find it in the GitHub repository.
"},{"location":"zengin/scripts/extenders/ikarus/examples/#open-focused-chest-or-door","title":"Open focused chest or door","text":"func void OpenFocussedChestOrDoor() \n{\n var oCNpc her; her = Hlp_GetNpc(hero);\n\n // No focus vob at all?\n if (!her.focus_vob) \n {\n Print (\"No focus!\");\n return;\n };\n\n // Focus vob not a lockable vob?\n if (!Hlp_Is_oCMobLockable(her.focus_vob))\n {\n Print (\"No chest or door in focus!\");\n return;\n };\n\n var oCMobLockable Lockable;\n Lockable = MEM_PtrToInst (her.focus_vob);\n\n if (Lockable.bitfield & oCMobLockable_bitfield_locked) \n {\n Lockable.bitfield = Lockable.bitfield & ~ oCMobLockable_bitfield_locked;\n Print (ConcatStrings (\"Opened the following vob: \", Lockable._zCObject_objectName));\n } \n else\n {\n Print (ConcatStrings ( Lockable._zCObject_objectName, \"wasn't even complete!\"));\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#print-camera-position","title":"Print camera position","text":"func void PrintCameraPos()\n{\n // Initialize global instances (which only exist once):\n // Initializes MEM_World, MEM_Game, etc. including MEM_Camera\n MEM_InitGlobalInst();\n\n /* The camera object is not a vob (but something abstract), \n do not know where and how there are position data.\n I prefer to work on the camera vob : */\n var zCVob camVob;\n camVob = MEM_PtrToInst (MEM_Camera.connectedVob);\n\n /* Here you have to know how the transformation matrix is structured:\n\n It consists of three vectors, the x, y and z directions of the local coordinate system of the camera vob\n in world coordinates (where z specifies the\n line of sight). These vectors are\n denoted by v1, v2, v3.\n In addition, in the 4th column there is the translation,\n that is, the position of the camera.\n\n v1_x v2_x v3_x x\n v1_y v2_y v3_y y\n v1_z v3_z v3_z z\n 0 0 0 0\n\n The matrix is stored row by row in memory.\n Since we are interested in the last column are the indices\n in the trafoWorld Array 3, 7 and 11 that we need. */\n\n Print (ConcatStrings (\"x: \",IntToString(roundf(camVob.trafoObjToWorld[3]))));\n Print (ConcatStrings (\"y: \",IntToString(roundf(camVob.trafoObjToWorld[7]))));\n Print (ConcatStrings (\"z: \",IntToString(roundf(camVob.trafoObjToWorld[11]))));\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#start-rain","title":"Start rain","text":"func void StartRain()\n{\n // Initialize global instances\n // This also includes Skycontroller\n MEM_InitGlobalInst(); \n\n // start at the beginning of the day (12:00 noon)\n MEM_SkyController.rainFX_timeStartRain = 0; // FLOATNULL constant\n // end at the end of the day (12:00 noon of the next day)\n MEM_SkyController.rainFX_timeStopRain = 1065353216; // FLOATONE constant\n\n /* Note: The start and end times are floating point numbers.\n * 0 stands for the beginning of the day 1 for the end of the day.\n * a day in the game begins at 12:00 p.m.\n * For the structure of the floating point format, google for IEEE-745.*/\n\n /* Result: rain all day! (unless you are in a zone\n * in which it snows, then snow all day) */\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#nested-loop","title":"Nested loop","text":"// Should enumerate all pairs (x,y) with 0 <= x < max_x, 0 <= j < max_y\n\nfunc void printpairs(var int max_x, var int max_y)\n{\n // Initialize labels\n MEM_InitLabels();\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n var int x_loop; x_loop = MEM_StackPos.position;\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n var int y_loop; y_loop = MEM_StackPos.position;\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n // continue y_loop \n MEM_StackPos.position = y_loop;\n };\n x += 1;\n // continue x_loop\n MEM_StackPos.position = x_loop;\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#calling-a-function-by-their-name","title":"Calling a function by their name","text":"// This example doesn't show why MEM_CallByString * is useful, but how to use the function.\n\nvar zCVob someObject;\nfunc int MyFunction(var int param1, var string str1, var int param2, var string str2)\n{\n Print (ConcatStrings (str1, str2)); //(*)\n return 100 * param1 + param2;\n};\n\nfunc void foo()\n{ \n var int result;\n\n // The following code is in this case equivalent to:\n // result = MyFunction(42, \"Hello\", 23, \"World!\");\n\n // Lay the call arguments on the call stack\n MEM_PushIntParam (42);\n MEM_PushStringParam (\"Hello \");\n MEM_PushIntParam (23);\n MEM_PushStringParam (\"World!\");\n\n MEM_CallByString (\"MYFUNCTION\");\n\n // the function puts the result (of type int in this case) on the stack\n // we pop the int result and save it to a variable\n result = MEM_PopIntResult();\n\n // print the result\n Print (IntToString (result));\n};\n\n/*\n Note: Since symbol indices are continuous and someObject's symbol index \n is simply given by someObject itself, could\n MEM_CallByString(\"MYFUNCTION\"); \n also be replaced here by \n MEM_CallByID(someObject + 1);\n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/","title":"Floats","text":""},{"location":"zengin/scripts/extenders/ikarus/floats/#floats","title":"Floats","text":"This part of ikarus implements support for 32 bit IEEE 754 floats in Daedalus. The script was originally created to edit zFLOAT
and zREAL
variables, but can also be used to arithmetic operations on real float values (not to be confused with Daedalus floats).
"},{"location":"zengin/scripts/extenders/ikarus/floats/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#implementation","title":"Implementation","text":" float.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/floats/#functions","title":"Functions","text":"Danger
Ikarus floats are saved as int but it doesn't mean that you can use arithmetic operators on them. All operations on floats must be done with functions listed below.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#mkf","title":"mkf
","text":"mkf
(make float) Converts the input integer x to a float value.
func int mkf(var int x)\n
Parameters var int x
The input integer Return value
The function returns the float representation of the input integer x.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#truncf","title":"truncf
","text":"truncf
(truncate float) Truncates the decimal part of the input float x.
func int truncf(var int x)\n
Parameters var int x
The input float Return value
The function returns the integer part of the input float x by discarding the decimal part.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#roundf","title":"roundf
","text":"roundf
(round float) Rounds the input float x to the nearest integer value.
func int roundf(var int x)\n
Parameters var int x
The input float Return value
The function returns the nearest integer value to the input float x. If the decimal part is exactly halfway between two integers, the function rounds to the nearest even integer.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#addf","title":"addf
","text":"addf
(add floats) Adds two ikarus floats together.
func int addf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the sum of the input floats x
and y
. (x + y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#subf","title":"subf
","text":"subf
(subtract floats) Subtracts the second float from the first float.
func int subf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the difference between the first float x
and the second float y
. (x - y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#negf","title":"negf
","text":"negf
(negate float) Negates the input float.
func int negf(var int x)\n
Parameters var int x
The input float Return value
The function returns the negation of the input float x
.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#mulf","title":"mulf
","text":"mulf
(multiply floats) Multiplies two ikarus floats.
func int mulf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the product of multiplying the input floats x and y. (x * y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#divf","title":"divf
","text":"divf
(divide floats) Divides two ikarus floats.
func int divf(var int x, var int y)\n
Parameters var int x
The dividend float var int y
The divisor float Return value
The function returns the quotient of dividing the input float x by y. (x / y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#invf","title":"invf
","text":"invf
(inverse float) Computes the inverse of the input float.
func int invf(var int x)\n
Parameters var int x
The input float Return value
The function returns the inverse of the x
, calculated as 1/x
.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#gf","title":"gf
","text":"gf
(greater) Checks if the first float is greater than the second float.
func int gf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is greater than y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#gef","title":"gef
","text":"gef
(greater or equal) Checks if the first float is greater than or equal to the second float.
func int gef(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is greater than or equal to y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#lf","title":"lf
","text":"lf
(lower) Checks if the first float is less than the second float.
func int lf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is less than y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#lef","title":"lef
","text":"lef
(lower or equal) Checks if the first float is less than or equal to the second float.
func int lef(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is less than or equal to y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrf","title":"sqrf
","text":"!!! function \"`sqrf`\"\n(square float) Calculates the square of the float.\n```dae\nfunc int sqrf(var int x)\n```\n**Parameters**\n\n- `#!dae var int x` \n The input float\n\n**Return value**\n\nThe function returns the square of the input float `x`, computed as `x * x`.\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrtf","title":"sqrtf
","text":"!!! function \"`sqrtf`\"\n(square root float) Calculates the square root of the float.\n```dae\nfunc int sqrtf(var int x)\n```\n**Parameters**\n\n- `#!dae var int x` \n The input float\n\n**Return value**\n\nThe function returns the square root of the input float `x`.\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrtf_approx","title":"sqrtf_approx
","text":"sqrtf_approx
Calculates the approximate square root of a float.
func int sqrtf_approx(var int f)\n
Parameters var int f
The input float Return value
The function returns the approximate square root of the input float as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#absf","title":"absf
","text":"absf
(absolute value) Computes the absolute value of a float.
func int absf(var int x)\n
Parameters var int x
The input float Return value
The function returns the absolute value of the input float x
, which is the value without the negative sign (if present).
"},{"location":"zengin/scripts/extenders/ikarus/floats/#fracf","title":"fracf
","text":"fracf
(fraction) Computes the fraction of two integers p and q.
func int fracf(var int p, var int q)\n
Parameters var int p
Numerator var int q
Denominator Return value
The function returns the fraction of p
divided by q
as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#castfromintf","title":"castFromIntf
","text":"castFromIntf
Converts an ikarus float to a Daedalus float.
func float castFromIntf(var int f)\n
Parameters Return Value
The function returns the value f
as a Daedalus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#casttointf","title":"castToIntf
","text":"castToIntf
Converts a Daedalus float to an ikarus float.
func int castToIntf(var float f)\n
Parameters var float f
Daedalus float Return Value
The function returns the value f
as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#tostringf","title":"toStringf
","text":"toStringf
Converts a float value to its string representation.
func string toStringf(var int x)\n
Parameters var int x
Input float value Return value
The function returns a string representation of the input float value.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#printf","title":"printf
","text":"printf
(print float) Prints the float on screen using Print()
.
func void printf(var int x)\n
Parameters var int x
The printed float "},{"location":"zengin/scripts/extenders/ikarus/floats/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/floats/#simple-operations","title":"Simple operations","text":"var int float1; float1 = mkf(5); // Create an Ikarus float with value 5\nvar int float2; float2 = mkf(2); // Create an Ikarus float with value 2\n\nvar int addResult; addResluts = addf(float1, float2); // Add float1 and float2\nvar int subResult; subResults = subf(float1, float2); // Subtract float2 from float1\nvar int mulResult; mulRelsults = mulf(float1, float2); // Multiply float1 by float2\nvar int divResult; divResults = divf(float1, float2); // Divide float1 by float2\n\nprintf(addResult); // Output: 7\nprintf(subResult); // Output: 3\nprintf(mulResult); // Output: 10\nprintf(divResult); // Output: 2.5\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/","title":"Ikarus Setup","text":""},{"location":"zengin/scripts/extenders/ikarus/setup/#ikarus-setup","title":"Ikarus Setup","text":""},{"location":"zengin/scripts/extenders/ikarus/setup/#download","title":"Download","text":"First you need to download ikarus from the official github repository. We recommend using the master branch as it contains the latest and most up-to-date version of Ikarus. However, you can also download a specific release if needed.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#file-location","title":"File location","text":"Before unpacking the downloaded archive it's needed to create a dedicated folder in <Gothic-dir>\\_work\\Data\\Scripts\\Content
directory. You can name this folder as you wish; in this guide, we'll refer to it as the \"MOD\" folder. Unpack the downloaded files into this newly created folder. The archiver should create a folder named Ikarus-master
or Ikarus-X.X.X
. For better readability change its name to the much simpler Ikarus
.
Tip
It's a good practice to delete any unused files, so delete files for other gothic version than this you are using.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#parsing","title":"Parsing","text":"Ikarus consists of three main parts, constants, classes and the Ikarus core. It's essential to parse these in a specific order. Additionally, there is a floats package which isn't essential, but it is highly recommended to parse it, especially if you are working with LeGo that depends on it.
The Ikarus Core is identical for both Gothic 1 and 2 and is contained in a single file, Ikarus.d
. However, there are separate files for the constants and classes for each engine, and they must be parsed correctly. Ikarus uses a C_NPC and therefore has to be parsed after the C_NPC class (after the classes.d
file). There are no other dependencies.
Since Ikarus 1.2.1 there is additional .src
file for each game engine, to simplify adding files to Gothic.src
Warning
Following example is for Gothic 2. If you are using Gothic 1 replace the G2
at the end of the file/directory name with G1
.
Gothic.srcGothic.src (Ikarus 1.2.1+) _INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\Ikarus_Const_G2.d\nMOD\\IKARUS\\EngineClasses_G2\\*.d\nMOD\\IKARUS\\Ikarus.d\nMOD\\IKARUS\\float.d\n
_INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G2.SRC\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/#initialization","title":"Initialization","text":"Before you can use Ikarus in your scripts, it must be properly initialized. The initialization process differs between Gothic 1 and Gothic 2.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#mem_initall","title":"MEM_InitAll
","text":"This is main ikarus initialization function, however it consists of some smaller initialization functions.
DeclarationDefinitionList of functions func void MEM_InitAll()\n
func void MEM_InitAll() {\n if (!MEMINT_ReportVersionCheck()) {\n return;\n };\n\n MEM_ReinitParser(); /* depends on nothing */\n MEM_InitLabels(); /* depends in MEM_ReinitParser */\n MEM_InitGlobalInst(); /* depends on MEM_ReinitParser */\n\n /* now I can use MEM_ReplaceFunc, MEM_GetFuncID */\n MEM_GetAddress_Init(); /* depends on MEM_ReinitParser and MEM_InitLabels */\n /* now the nicer operators are available */\n\n MEM_InitStatArrs(); /* depends on MEM_ReinitParser and MEM_InitLabels */\n ASMINT_Init();\n\n MEMINT_ReplaceLoggingFunctions();\n MEMINT_ReplaceSlowFunctions();\n MEM_InitRepeat();\n\n /* takes a wail the first time it is called.\n call it to avoid delay later */\n var int dump; dump = MEM_GetFuncIDByOffset(0);\n};\n
MEM_ReinitParser MEM_InitLabels MEM_InitGlobalInst MEM_GetAddress_Init MEM_InitStatArrs ASMINT_Init MEM_InitRepeat "},{"location":"zengin/scripts/extenders/ikarus/setup/#gothic-1","title":"Gothic 1","text":"To initialize Ikarus in Gothic 1 you must define your own INIT_GLOBAL
function at the top of the Startup.d
file. Then the INIT_GLOBAL
should be called in every INIT_<location>
function (e.g. INIT_SURFACE
,INIT_OLDCAMP
etc.). INIT_SUB_<location>
functions can be skipped in that process.
Then in your INIT_GLOBAL
function you call MEM_InitAll()
initialization function.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n};\n\n// [...]\n\nfunc VOID INIT_SURFACE ()\n{\n Init_Global();\n INIT_SUB_SURFACE ();\n};\n// [...]\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/#gothic-2","title":"Gothic 2","text":"Gothic 2 has its own INIT_GLOBAL
function, so the initialization process is much simpler. All you have to do is to call MEM_InitAll()
in INIT_GLOBAL
function located in the Startup.d
file.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n};\n\n// [...]\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/","title":"Arrays (zCArray)","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#arrays-zcarray","title":"Arrays (zCArray)","text":"Set of function for working with ZenGin's zCArray
data structure.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraycreate","title":"MEM_ArrayCreate
","text":"MEM_ArrayCreate
Creates an empty zCArray
(allocates memory) and returns a pointer to it.
func int MEM_ArrayCreate()\n
Return value The function returns a pointer to the created zCArray
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayfree","title":"MEM_ArrayFree
","text":"MEM_ArrayFree
Frees the memory allocated for a zCArray
and its data.
func void MEM_ArrayFree(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
to be freed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayclear","title":"MEM_ArrayClear
","text":"MEM_ArrayClear
Clears the data of a zCArray
, freeing the memory used by its elements. The array becomes empty.
func void MEM_ArrayClear (var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
to be cleared "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraysize","title":"MEM_ArraySize
","text":"MEM_ArraySize
Returns the size (number of elements) of an array.
func int MEM_ArraySize(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns a number of a zCArray
elements.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraywrite","title":"MEM_ArrayWrite
","text":"MEM_ArrayWrite
Writes a value at a specific position in the zCArray
.
func void MEM_ArrayWrite(var int zCArray_ptr, var int pos, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int pos
Position in the array where the value will be written var int value
Value to be written "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayread","title":"MEM_ArrayRead
","text":"MEM_ArrayRead
Reads the value at a specific position in the zCArray
.
func int MEM_ArrayRead(var int zCArray_ptr, var int pos)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int pos
Position in the array from which the value will be read Return value
The function returns the value at a specific position in the zCArray
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayinsert","title":"MEM_ArrayInsert
","text":"MEM_ArrayInsert
Appends a value to the end of the zCArray
. The array is automatically resized if it is too small.
func void MEM_ArrayInsert (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be inserted "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraypush","title":"MEM_ArrayPush
","text":"MEM_ArrayPush
Alias for MEM_ArrayInsert
, inserts a value at the end of the zCArray
.
func void MEM_ArrayPush (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be inserted "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraypop","title":"MEM_ArrayPop
","text":"MEM_ArrayPop
Removes and returns the last element from the zCArray
.
func int MEM_ArrayPop(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns the element removed from the end of an array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraytop","title":"MEM_ArrayTop
","text":"MEM_ArrayTop
Returns the last element of the zCArray
without removing it.
func int MEM_ArrayTop(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns the last element of an array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayindexof","title":"MEM_ArrayIndexOf
","text":"MEM_ArrayIndexOf
Searches the zCArray
for the first occurrence of a value
and returns its index.
func int MEM_ArrayIndexOf(var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to search for Return value
The function returns the index of a first occurrence of a value
. If not found -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremoveindex","title":"MEM_ArrayRemoveIndex
","text":"MEM_ArrayRemoveIndex
Removes the element at a specific index from the zCArray
.
func void MEM_ArrayRemoveIndex (var int zCArray_ptr, var int index)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int index
Index of the element to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremovevalue","title":"MEM_ArrayRemoveValue
","text":"MEM_ArrayRemoveValue
Removes all occurrences of a value from the zCArray
.
func void MEM_ArrayRemoveValue (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremovevalueonce","title":"MEM_ArrayRemoveValueOnce
","text":"MEM_ArrayRemoveValueOnce
Removes the first occurrence of a value from the zCArray
. If value is not found, a warning is issued.
func void MEM_ArrayRemoveValueOnce (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraysort","title":"MEM_ArraySort
","text":"MEM_ArraySort
Sorts the elements of the zCArray
in ascending order.
func void MEM_ArraySort(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayunique","title":"MEM_ArrayUnique
","text":"MEM_ArrayUnique
Removes duplicate elements from the zCArray
.
func void MEM_ArrayUnique(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraytostring","title":"MEM_ArrayToString
","text":"MEM_ArrayToString
Converts the zCArray
to a string representation.
func string MEM_ArrayToString (var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns a string representation of a given array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/","title":"Ikarus Machine Code Implementation (ASM)","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#ikarus-machine-code-implementation-asm","title":"Ikarus Machine Code Implementation (ASM)","text":"Machine code refers to a program or program segment written in machine language, which can be directly executed by a processor without further translation steps. The relevant machine language for us is that belonging to the x86 processor architecture. All machine instructions, what they do, and how they are encoded in machine language can be found in the Intel Manuals.
In practice, dealing with (abstract) machine instructions and manually translating them into (concrete) machine code is rarely necessary due to its complexity.
However, machine code can be useful for performing technical tasks that cannot be expressed in Daedalus directly. For example, the CALL package use the ASM function set as a basis.
Note
The functions in this chapter have the ASM_
prefix for Assembly (language). Assembly language is a human-readable language with one-to-one correspondences to machine language. Strictly speaking, the ASM_
prefix is misleading here, as it pertains to machine code rather than assembly language. However, conceptually, the two are closely related.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#opcodes","title":"Opcodes","text":"The code defines several constants that represent different machine code instructions. Each constant is assigned a hexadecimal value and corresponds to a specific machine code instruction. Here is a link to all instructions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#internal-stack","title":"Internal Stack","text":"The code includes an internal stack implementation, allowing the storage of data. The stack is already used at two points:
When calling an engine function, the address of the current run is stored in the internal stack. When nesting the use of the CALL package, a push and pop operation is performed to manage the context. The internal stack is implemented using an array, and the following functions are provided:
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_push","title":"ASMINT_Push
","text":"ASMINT_Push
Pushes the specified data
onto the internal stack.
func void ASMINT_Push(var int data)\n
Parameters var int data
Data pushed onto internal stack "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_pop","title":"ASMINT_Pop
","text":"ASMINT_Pop
Pops and returns the topmost data from the internal stack.
func int ASMINT_Pop()\n
Return value The function returns a data popped form the internal stack.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#functions-core","title":"Functions (Core)","text":"The ASM core functionality provides a framework for assembling machine code instructions and executing them. The following functions are included:
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_init","title":"ASMINT_Init
","text":"ASMINT_Init
Initializes the ASM system by creating an internal stack and finding function addresses.
func void ASMINT_Init()\n
Tip
It's worth noting that ASMINT_Ini
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_open","title":"ASM_Open
","text":"ASM_Open
Changes the size of the memory allocated at the start o the dictation
The memory in which the machine code is stored is allocated at the beginning of the dictation. If this function isn't called a default size (see Constant below) is allocated by ASM
or ASM_Here
function. The 256 bytes is often sufficient for simple applications, but if more memory is required, this function must be called at the beginning of the dictation.
func void ASM_Open(var int space)\n
Parameters var int space
Space allocated for machine code (in bytes) Constant
ASM_StandardStreamLength
constant defines the default space available for an Assembler sequence (in bytes).
const int ASM_StandardStreamLength = 256;\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm","title":"ASM
","text":"ASM
Writes machine code instructions to the stream.
Using this function it is possible to dictate machine code little by little. The data
bytes of the length
(maximum 4!) are appended to the previously dictated part. This creates a program piece by piece that can be executed by the processor.
func void ASM(var int data, var int length)\n
Parameters var int data
The machine code instruction or its part var int length
Length of the data
(max 4 bytes) ASM_1ASM_2ASM_3ASM_4"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_1","title":"ASM_1
","text":"ASM_1
ASM
with length
parameter hardcoded to 1. Writes one byte machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
One byte machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_2","title":"ASM_2
","text":"ASM_2
ASM
with length
parameter hardcoded to 2. Writes two bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Two bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_3","title":"ASM_3
","text":"ASM_3
ASM
with length
parameter hardcoded to 3. Writes three bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Three bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_4","title":"ASM_4
","text":"ASM_4
ASM
with length
parameter hardcoded to 4. Writes four bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Four bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_here","title":"ASM_Here
","text":"ASM_Here
Provides, the address of the cursor, i.e., the address of the location that will be described next by a call to ASM
. It is guaranteed that the location where the code is written is also the location where it will be executed.
func int ASM_Here()\n
Return value
The function returns an address that is the current position in the machine code stream.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_close","title":"ASM_Close
","text":"ASM_Close
Finalizes the stream by adding a return instruction and returns the starting address of the stream. This pointer can now be passed to at any time and any number of times to execute the machine code.
Warning
The memory area obtained by ASM_Close
must be released manually using MEM_Free
to avoid memory leaks. It is probably sufficient for almost all practical purposes.
func int ASM_Close()\n
Return value The function returns a starting address of the stream (pointer to the stream).
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_run","title":"ASM_Run
","text":"ASM_Run
Executes a machine code (stream) from a pointer.
Note
ASM_Run
can also be used to call engine functions with no parameters and no relevant return value. In this case ptr
would simply have to point to the function to be executed in the code segment.
func void ASM_Run(var int ptr)\n
Parameters var int ptr
Pointer to the executed code (returned form ASM_Close
) "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_runonce","title":"ASM_RunOnce
","text":"ASM_RunOnce
Executes the code dictated up to that point, similar to how an external function is executed. After that the code is released, and new code can be dictated.
func void ASM_RunOnce()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#example","title":"Example","text":"The following function sets the NPC passed as slf as the player, as if you had pressed O in Marvin mode with this NPC in focus. This is so short because there is already a function for this exact purpose, it's just not normally accessible from the scripts. It is therefore sufficient to write assembly code that pushes the parameter of the function (the this
pointer) into the appropriate register and then calls the function.
func void SetAsPlayer(var C_NPC slf) { /* Address of the function */\n const int oCNpc__SetAsPlayer = 7612064; //0x7426A0 (Gothic2.exe)\n\n var int slfPtr;\n slfPtr = MEM_InstToPtr (slf);\n\n //mov ecx slfPtr\n ASM_1(ASMINT_OP_movImToECX); /* move a value to ecx */\n ASM_4(slfPtr); /* a value */\n\n //call oCNpc__SetAsPlayer\n ASM_1(ASMINT_OP_call);\n ASM_4(oCNpc__SetAsPlayer - ASM_Here() - 4);\n\n ASM_RunOnce(); /* return will be added automatically */\n};\n
Note
Call targets are specified relative to the instruction that would have been executed after the actual call instruction. Therefore, both ASM_Here() and the subtraction of 4 in the call parameter are necessary.
The above example describes, among other things, CALL__thiscall
function form the CALL Package that can be also used to implement SetAsPlayer
.
func void SetAsPlayer(var C_NPC slf) { \n const int oCNpc__SetAsPlayer = 7612064;\n CALL__thiscall(MEM_InstToPtr(slf), oCNpc__SetAsPlayer);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/","title":"CALL Package","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call-package","title":"CALL Package","text":"This part of Ikarus makes possible to call engine functions directly from scripts.
In order to be able to invoke an engine function, you must know some of its properties. This includes the number and types of parameters, the type of return value, address of function and calling convention.
Knowledge about engine functions can be obtained using tools like IDA, which can analyze and convert GothicMod.exe / Gothic2.exe into a more human-readable format.
Info
In fact, machine code execution (ASM) is part of the CALL package, but due to its complexity, this functionality is discussed in a separate article.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call-modes","title":"Call modes","text":"There are two modes:
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#disposable","title":"Disposable","text":"The simple mode that produces a disposable call that is used only once. All parameters are hardcoded.
func int hero_GetAssessEnemy() {\n const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400\n\n CALL_IntParam(_@(PERC_ASSESSENEMY));\n CALL_PutRetValTo(_@(funcID));\n CALL__thiscall(_@(hero), oCNpc__GetPerceptionFunc);\n\n var int funcID;\n return +funcID;\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#recyclable","title":"Recyclable","text":"The second version produces code that can be used more than once. Instead of the parameters the user specifies the address where the parameters are to be taken from. In addition to executing the code, the user will receive an address that he can use to repeat the call. This is much faster than rebuilding the call from scratch.
func int Npc_GetPercFunc(var C_Npc npc, var int type) {\n const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400\n\n var int npcPtr; npcPtr = _@(npc);\n\n const int call = 0;\n if (CALL_Begin(call)) {\n CALL_IntParam(_@(type));\n CALL_PutRetValTo(_@(funcID));\n CALL__thiscall(_@(npcPtr), oCNpc__GetPerceptionFunc);\n call = CALL_End();\n };\n\n var int funcID;\n return +funcID;\n};\n
Receives a pointer. In case the pointer is non-zero, the code at this position is executed and 0 is returned. In case pointer is zero, the current mode is changed into recyclable mode, this means that the call functions expect instructions to build a recyclable call. This mode will continue until CALL_End()
. This allows code like this:
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#start-and-end","title":"Start and End","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_open","title":"CALL_Open
","text":"CALL_Open
Initializes a Recyclable call mode.
func void CALL_Open()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_begin","title":"CALL_Begin
","text":"CALL_Begin
A practical wrapper for CALL_Open
. Makes a call if it had been already created, initializes it otherwise.
func int CALL_Begin(var int ptr)\n
Parameters var int ptr
Zero if you need to create a new recyclable function to be called (usually, before first use). In this case CALL_Open
is called and CALL_Begin
returns 1
. Return Value
The function returns 1
if the new call has been created, 0
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_close","title":"CALL_Close
","text":"CALL_Close
Finalizes a function call in recyclable mode, restoring the previous execution context.
func int CALL_Close()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_end","title":"CALL_End
","text":"CALL_End
Finalizes a function call, pushes the pointer onto the stack, and runs the associated assembly code (makes an actual call).
func int CALL_End()\n
Return Value
The function returns a pointer that could be used to repeat the call.
Tip
CALL_Close
only finalizes the function call, returning the pointer, while CALL_End
additionally handles pushing the pointer onto the stack and running associated assembly code.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#passing-parameters","title":"Passing parameters","text":"Parameters must be arranged on the machine stack from right to left i.e. from the parameter on the far right to the parameter on the far left. These functions generate machine code that will place parameters on the machine stack when executed.
Note
These functions do not impose any parameters on the Machine stack. Exactly it should say: You create the machine code that will put parameters on the machine stack when it is executed. And it is only carried out in the second step with the announcement of the calling convention.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_intparam","title":"CALL_IntParam
","text":"CALL_IntParam
Passes an integer (int32
) as a parameter to the called function.
func void CALL_IntParam(var int param)\n
Parameters var int param
Address of an integer to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_floatparam","title":"CALL_FloatParam
","text":"CALL_FloatParam
Passes an IEEE 7554 floating-point number (single
/ zREAL
) as a parameter to the called function.
func void CALL_FloatParam(var int param)\n
Parameters var int param
Address of a float to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_ptrparam","title":"CALL_PtrParam
","text":"CALL_PtrParam
Passes a pointer (void*
) as a parameter to the called function.
func void CALL_PtrParam(var int param)\n
Parameters var int param
Pointer to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_zstringptrparam","title":"CALL_zStringPtrParam
","text":"CALL_zStringPtrParam
Passes a string (zString*
) as a parameter to the called function.
func void CALL_zStringPtrParam(var string param)\n
Parameters var string param
String to be passed Warning
This function only works when writing a disposable call!
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_cstringptrparam","title":"CALL_cStringPtrParam
","text":"CALL_cStringPtrParam
Passes a char array (char **
) as a parameter to the called function.
func void CALL_cStringPtrParam(var string param)\n
Parameters var string param
String to be passed as character array` Warning
This function only works when writing a disposable call!
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_structparam","title":"CALL_StructParam
","text":"CALL_StructParam
Passes a structure (struct) as a parameter to the called function.
func void CALL_StructParam(var int ptr, var int words)\n
Parameters var int param
Pointer to the object var int words
Size of a structure (1 word = 32 bits) Note
CALL_IntParam
, CALL_FloatParam
, and CALL_PtrParam
are functionally identical and are differentiated for code readability.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#the-call","title":"The call","text":"The calling convention determines how the function's parameters are passed. IDA or another disassembler can be used to identify the convention used by a specific engine function.
The announcement of the calling convention, i.e. the call of one of the four functions below is also the time of calling the function. In particular, all parameters must already be specified at this point.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__stdcall","title":"CALL__stdcall
","text":"CALL__stdcall
Calls a function with __stdcall
(Standard Call) calling convention.
func void CALL__stdcall(var int adr)\n
Parameters var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__thiscall","title":"CALL__thiscall
","text":"CALL__thiscall
Calls a function with __thiscall
calling convention. Used with a member functions.
func void CALL__thiscall(var int this, var int adr)\n
Parameters var int this
Pointer to the owner class object passed as a this
parameter var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__cdecl","title":"CALL__cdecl
","text":"CALL__cdecl
Calls a function with __cdecl
calling convention. Used with non-Windows API and non-class functions.
func void CALL__cdecl (var int adr)\n
Parameters var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__fastcall","title":"CALL__fastcall
","text":"CALL__fastcall
Calls a function with __fastcall
calling convention.
func void CALL__fastcall(var int ecx, var int edx, var int adr)\n
Parameters var int ecx
First parameter of a function var int edx
Second parameter of a function var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#return-value","title":"Return Value","text":"As soon as the function call has taken place, i.e. after step 2, the return value can be queried. The following functions interpret the return value (usually this is the content of EAX immediately after the call) in the manner suggested in the function name. The result is then returned in a manner usable in Daedalus.
Note
Some return values are not stored in the EAX. In that case the call of the special function RetValIs
is required to get the return value.
Following functions are provided: CALL_RetValIsFloat
, CALL_RetValIszString
, CALL_RetValIsStruct
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_putretvalto","title":"CALL_PutRetValTo
","text":"CALL_PutRetValTo
Simply places the return value to the given address (mostly the address of a daedalus integer). Must be called before The Call function.
func void CALL_PutRetValTo(var int adr)\n
Parameters var int adr
Destination address of the return value "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasint","title":"CALL_RetValAsInt
","text":"CALL_RetValAsInt
Retrieves an integer returned by the called function.
func int CALL_RetValAsInt()\n
Return value The function returns an integer returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalisfloat","title":"CALL_RetValIsFloat
","text":"CALL_RetValIsFloat
Specifies that the return value is a float. Must be called before The Call function to allow getting the return value with CALL_RetValAsFloat
.
func void CALL_RetValIsFloat()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasfloat","title":"CALL_RetValAsFloat
","text":"CALL_RetValAsFloat
Retrieves a float returned by the called function.
func int CALL_RetValAsFloat()\n
Return value The function returns a float returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasptr","title":"CALL_RetValAsPtr
","text":"CALL_RetValAsPtr
Retrieves a pointer (void*
) returned by the called function.
func int CALL_RetValAsPtr()\n
Return value The function returns a pointer returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalisstruct","title":"CALL_RetValIsStruct
","text":"CALL_RetValIsStruct
Specifies that the return value is a Structure. Must be called before The Call function to allow getting the return value with CALL_RetValAsStructPtr
.
func void CALL_RetValIsStruct(var int size)\n
Parameters var int size
Size of the returned structure in bytes Danger
If the return value is a structure with a size larger than 32 bit, the space for the return value has to be allocated by the caller (this is us).The address to the allocated memory is expected on the stack as an additional parameter (pushed last).
Warning
It is in your responsibility to free the structure memory, when the return value is not needed any more.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasstructptr","title":"CALL_RetValAsStructPtr
","text":"CALL_RetValAsStructPtr
Retrieves a pointer to the structure returned by the called function and converts it to the instance. Can be used to make an assignment to an instance, for example an assignment to a var zCVob
if the return value is a pointer to a zCVob
.
func MEMINT_HelperClass CALL_RetValAsStructPtr()\n
Return value The function returns an instance returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvaliszstring","title":"CALL_RetValIszString
","text":"CALL_RetValIszString
Specifies that the return value is a zString
(20 bytes structure). Must be called before The Call function to allow getting the return value with CALL_RetValAszStringPtr
and CALL_RetValAszString
.
func string CALL_RetValAszString()\n
Note
CALL_RetValAszStringPtr
and CALL_RetValAszString
are quite different and should not be confused. Using CALL_RetValAszString
frees up memory that may still be needed. In a reverse with CALL_RetValAszStringPtr
memory that is no longer needed is not freed and can cause memory leak.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalaszstringptr","title":"CALL_RetValAszStringPtr
","text":"CALL_RetValAszStringPtr
Retrieves a zString
pointer and converts it to the daedalus string. (don't frees the memory)
func string CALL_RetValAszStringPtr()\n
Return value The function returns a daedalus string form a zString
returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalaszstring","title":"CALL_RetValAszString
","text":"CALL_RetValAszString
Retrieves a zString
pointer and converts it to the daedalus string. (frees the memory)
func string CALL_RetValAszString()\n
Return value The function returns a daedalus string form a zString
returned by the previously called engine function.
Function author note A zString
is merely a special case of a structure, with the difference, that it is used as a primitive datatype. Nobody will be willing to use it as a pointer to some memory or an instance in Daedalus. This function copies the contents of the zString
into a daedalus string and frees the zString
afterwards.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#apply-overlay-disposable","title":"Apply overlay (Disposable)","text":"// .text:0072D2C0:int __thiscall oCNpc::ApplyOverlay(class zSTRING const &)\n\nfunc void example1(){\n const int oCNpc__ApplyOverlay = 7525056; //0x72D2C0 (G2A)\n CALL_zStringPtrParam (\"HUMANS_MILITIA.MDS\");\n CALL__thiscall (MEM_InstToPtr (hero), oCNpc__ApplyOverlay);\n //We are not interested in the return value here.\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#get-time-as-string-disposable","title":"Get time as string (Disposable)","text":"e.g. \"7:30\"
for half past seven in the morning
// .text:00780EC0:class zSTRING __thiscall oCWorldTimer::GetTimeString(void)\n\nfunc void example2(){\n const int oCWorldTimer__GetTimeString = 7868096; //780EC0 (G2A)\n CALL_RetValIszString();\n CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer), oCWorldTimer__GetTimeString );\n PrintDebug (CALL_RetValAszString());\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#get-the-sky-time-disposable","title":"Get the \"sky time\" (Disposable)","text":"Sky time is a floating point value between 0 and 1 that jumps back from 1 to 0 at noon.
// .text:00781240:float __thiscall oCWorldTimer::GetSkyTime(void)\n\nfunc int GetSkyTime() {\n const int oCWorldTimer__GetSkyTime = 7868992; //0x781240\n CALL_RetValIsFloat();\n CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer),\n oCWorldTimer__GetSkyTime);\n\n return CALL_RetValAsFloat();\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#delete-vob-recyclable","title":"Delete Vob (Recyclable)","text":"Call of the oCWorld.RemoveVob
. MEM_DeleteVob
is an ikarus built-in function.
func void MEM_DeleteVob(var int vobPtr) {\n var int world; world = MEM_Game._zCSession_world;\n\n const int call = 0;\n if (CALL_Begin(call)) {\n /* oCWorld.RemoveVob */\n CALL_IntParam(_@(vobPtr));\n CALL__thiscall(_@(world), MEMINT_SwitchG1G2(7171824, 7864512));\n\n call = CALL_End();\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/","title":"Debug","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#debug","title":"Debug","text":"A set of debugging and error-handling functions for mod development with Ikarus.
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_checkversion","title":"MEM_CheckVersion
","text":"MEM_CheckVersion
Checks if the version of Ikarus is the specified version or newer.
func int MEM_CheckVersion(var int base, var int major, var int minor)\n
Parameters var int base
Base version number var int major
Major revision number var int minor
Minor revision number Return value
The function returns TRUE
if the version of Ikarus is the specified version or newer, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_setshowdebug","title":"MEM_SetShowDebug
","text":"MEM_SetShowDebug
Sets the variable that is also toggled by the toggle debug
command. As a result, messages outputted by PrintDebug
are directed to the zSpy
func void MEM_SetShowDebug(var int on)\n
Parameters var int on
Specifies whether to turn on (TRUE
) or off (FALSE
) debug information. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_sendtospy","title":"MEM_SendToSpy
","text":"MEM_SendToSpy
Sends a message to the debugging console.
func void MEM_SendToSpy(var int errorType, var string text)\n
Parameters var int errorType
Type of error (e.g., zERR_TYPE_FAULT
, zERR_TYPE_WARN
, zERR_TYPE_INFO
) var string text
The message to be sent. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_errorbox","title":"MEM_ErrorBox
","text":"MEM_ErrorBox
Displays an error message in a message box.
func void MEM_ErrorBox(var string text)\n
Parameters var string text
The error message to be displayed. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_printstacktrace","title":"MEM_PrintStackTrace
","text":"MEM_PrintStackTrace
Prints the stack trace.
func void MEM_PrintStackTrace()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_error","title":"MEM_Error
","text":"MEM_Error
Handles a fatal error, displaying the error message and printing the stack trace.
func void MEM_Error(var string error)\n
Parameters var string error
The error message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_warn","title":"MEM_Warn
","text":"MEM_Warn
Handles a warning, displaying the warning message and printing the stack trace.
func void MEM_Warn(var string warn)\n
Parameters var string warn
The warning message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_info","title":"MEM_Info
","text":"MEM_Info
Handles an information message, printing it if enabled in the settings.
func void MEM_Info(var string info)\n
Parameters var string info
The information message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_assertfail","title":"MEM_AssertFail
","text":"MEM_AssertFail
Handles an assertion failure, reporting the error message as a fatal error.
func void MEM_AssertFail(var string assertFailText)\n
Parameters var string assertFailText
The assertion failure message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_debug","title":"MEM_Debug
","text":"MEM_Debug
Freely configurable debug channel. See how to setup it in the Constants article.
func void MEM_Debug(var string message)\n
Parameters var string message
The debug message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#memint_switchg1g2","title":"MEMINT_SwitchG1G2
","text":"MEMINT_SwitchG1G2
Switches between values based on the game version. Used mainly to change addresses in multi-platform hooks or function calls.
func int MEMINT_SwitchG1G2(var int g1Val, var int g2Val)\n
Parameters var int g1Val
The value to return if the game version is Gothic 1. var int g2Val
The value to return if the game version is Gothic 2. Return value
The function returns an appropriate value based on the game version.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/","title":"Configuration file access","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#configuration-file-access","title":"Configuration file access","text":"This part of Ikarus gives you access to Gothic.ini
and loaded mod configuration files.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#read-functions","title":"Read functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getcommandline","title":"MEM_GetCommandLine
","text":"MEM_GetCommandLine
Returns the contents of the command line passed to Gothic.
func string MEM_GetCommandLine()\n
Return value The function returns contents of the command line passed to Gothic. This could, for example, look like this:
\"-TIME:7:35 -GAME:TEST_IKARUS.INI -ZREPARSE -ZWINDOW -ZLOG:5,S -DEVMODE -ZMAXFRAMERATE:30\"
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getgothopt","title":"MEM_GetGothOpt
","text":"MEM_GetGothOpt
Searches the Gothic.ini
for an option.
func string MEM_GetGothOpt(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [GAME]
var string optionname
One setting entry like playLogoVideos
Return value
The function returns an option value as a string or empty string if option was not found.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getmodopt","title":"MEM_GetModOpt
","text":"MEM_GetModOpt
Searches the loaded mod ini file for option.
func void MEM_GetModOpt(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [INFO]
var string optionname
One setting entry like Title
Return value
The function returns an option value as a string or empty string if option was not found.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_gothoptsectionexists","title":"MEM_GothOptSectionExists
","text":"MEM_GothOptSectionExists
Checks whether a section exists in Gothic.ini
func int MEM_GothOptSectionExists(var string sectionname)\n
Parameters var string sectionname
Settings section like [GAME]
Return value
The function returns TRUE
if section exists FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_modoptsectionexists","title":"MEM_ModOptSectionExists
","text":"MEM_ModOptSectionExists
Checks whether a section exists in loaded mod ini file
func int MEM_ModOptSectionExists(var string sectionname)\n
Parameters var string sectionname
Settings section like [INFO]
Return value
The function returns TRUE
if section exists FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_gothoptexists","title":"MEM_GothOptExists
","text":"MEM_GothOptExists
Checks whether an option exists in Gothic.ini
func int MEM_GothOptExists(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [GAME]
var string optionname
One setting entry like playLogoVideos
Return value
The function returns TRUE
if option in a section exist FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_modoptexists","title":"MEM_ModOptExists
","text":"MEM_ModOptExists
Checks whether an option exists in loaded mod ini file
func int MEM_ModOptExists(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [INFO]
var string optionname
One setting entry like Title
Return value
The function returns TRUE
if option in a section exist FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#write-functions","title":"Write functions","text":"Warning
Mod configuration is never saved to disk, therefore no separate functions exist for writing to it.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setgothopt","title":"MEM_SetGothOpt
","text":"MEM_SetGothOpt
The option option
in the section section
is set to the value
. If the section and/or option does not exist, it will be created.
func void MEM_SetGothOpt(var string section, var string option, var string value)\n
Parameters var string section
The section where the option should be located var string option
Option to write/overwrite var string value
Value to set the option to "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_applygothopt","title":"MEM_ApplyGothOpt
","text":"MEM_ApplyGothOpt
Applies the changes and saves the ini to disk
func void MEM_ApplyGothOpt()\n
Tip
If you introduce new options, it is best to follow certain practices. It is a good practice to name your options in a clear manner and place them in a section named the same as your mod. Do not place your mod options into the [GAME]
or [PERFORMANCE]
sections.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#key-functions","title":"Key functions","text":"The Gothic.ini
contains the assignment of physical keys (e.g. \"W\") to logical keys (e.g. \"keyUp\").
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getkey","title":"MEM_GetKey
","text":"MEM_GetKey
Returns the primary key assigned to logical key.
func int MEM_GetKey(var string name)\n
Parameters var string name
Name of the logical key Return value
The function returns key assigned to logical key
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getsecondarykey","title":"MEM_GetSecondaryKey
","text":"MEM_GetSecondaryKey
Returns a secondary key assigned to logical key.
func int MEM_GetSecondaryKey(var string name)\n
Parameters var string name
Name of the logical key Return value
The function returns key assigned to logical key
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setkeys","title":"MEM_SetKeys
","text":"MEM_SetKeys
Sets keyboard keys of the logical key.
func void MEM_SetKeys(var string name, var int primary, var int secondary)\n
Parameters var string name
Name of the logical key var int primary
Primary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. var int secondary
Secondary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setkey","title":"MEM_SetKey
","text":"MEM_SetKey
Sets the primary keyboard key of the logical key.
func void MEM_SetKey(var string name, var int key)\n
Parameters var string name
Name of the logical key var int key
Primary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setsecondarykey","title":"MEM_SetSecondaryKey
","text":"MEM_SetSecondaryKey
Sets the secondary keyboard key of the logical key.
func void MEM_SetSecondaryKey(var string name, var int key)\n
Parameters var string name
Name of the logical key var int key
Secondary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/","title":"Jumps and Loops","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#jumps-and-loops","title":"Jumps and Loops","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#jumps","title":"Jumps","text":"Jumps in Ikarus are implemented by direct manipulation of the stack pointer, achieved with two lines of code. These lines enable the change of the current position within the parser stack, representing machine-level code generated during script compilation. By querying and setting this position, the execution flow can be redirected to a new location in the code.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#initialization","title":"Initialization","text":"To ensure the correct functioning of this jump mechanism, it is crucial to execute the MEM_InitLabels()
function once after loading a saved game. The recommended practice is to integrate this initialization function within INIT_GLOBAL
. It's only after MEM_InitLabels()
has been called that accessing MEM_StackPos.position
becomes valid.
func void MEM_InitLabels()\n
Tip
It's worth noting that MEM_InitLabels
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#usage","title":"Usage","text":" Jump flowchart
flowchart TD\nA(Start) --> B[\"var int label; \\n label = MEM_StackPos.position;\"];\nB --> C{Your code}\nC -->D[\"MEM_StackPos.position = label;\"];\nC --> E(End)\nD --> |Jump| B;
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#notes-and-warnings","title":"Notes and warnings","text":" Validity of Labels Labels become invalid after saving and loading. Consequently, labels should be used immediately, and there is generally no reason to persist them for an extended period.
Caution with Jumping Jumping between different functions without a clear understanding of the code structure can lead to unexpected issues. Similarly, using labels without a thorough comprehension of their purpose may result in undesired consequences. It's crucial to exercise caution, especially when making assignments involving labels.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples","title":"Examples","text":"Simple jump 'loop'Nested jump 'loop' The following code outputs the numbers from 0 to 42:
func void foo() {\n /* Initialization */\n MEM_InitLabels();\n var int count; count = 0;\n\n /* Record the execution position in label. */\n var int label;\n label = MEM_StackPos.position;\n /* <---- label now points here,\n * i.e. to the position AFTER the assignment of label. */\n\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n\n if (count <= 42) {\n /* Replace the execution position,\n * with the \"<-----\" the system then continues */\n MEM_StackPos.position = label;\n };\n\n /* Once 43 is reached, the \u201cloop\u201d is exited. */\n};\n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // Initialize labels\n MEM_InitLabels();\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n var int x_loop; x_loop = MEM_StackPos.position;\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n var int y_loop; y_loop = MEM_StackPos.position;\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n // continue y_loop \n MEM_StackPos.position = y_loop;\n };\n x += 1;\n // continue x_loop\n MEM_StackPos.position = x_loop;\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#label-and-goto","title":"Label and Goto","text":"Besides the normal jumps Ikarus implements MEM_Label
and MEM_Goto
functions. They work similar to the stack manipulation with var int label
but the interface is much more user-friendly and defining new variables is not needed.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#mem_label","title":"MEM_Label
","text":"MEM_Label
Function that works like a label = MEM_StackPos.position;
. You could jump to it with MEM_Goto
.
func void MEM_Label(var int lbl)\n
Parameters var int lbl
Number of the label, used for nested loop or multiple loops within one function "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#mem_goto","title":"MEM_Goto
","text":"MEM_Goto
Function that works like a MEM_StackPos.position = label;
. Executes a jump to a MEM_Label
with specified number.
func void MEM_Goto(var int lbl)\n
Parameters var int lbl
Number of the label, the function will jump to "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#usage_1","title":"Usage","text":"Usage of Label and Goto is probably self-explanatory, since it is same as in the regular Ikarus Jump. But before using it reading the Notes and warnings of the Jumps is recommended.
Label-Goto loop flowchart
flowchart TD\nA(Start) --> B[\"MEM_Label(0);\"];\nB --> C{Your code}\nC -->D[\"MEM_Goto(0);\"];\nC --> E(End)\nD --> |Jump| B;
Label-Goto loopfunc void LabelGoto_test() {\n var int i; \n MEM_Label(0);\n MEM_Debug(IntToString(i));\n i = i + 1;\n if(i >= 4)\n {\n return;\n };\n MEM_Goto(0);\n};\n\n// Results:\n// Info: 0 Q: Debug: 0\n// Info: 0 Q: Debug: 1\n// Info: 0 Q: Debug: 2\n// Info: 0 Q: Debug: 3\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_1","title":"Examples","text":"Simple Label-Goto 'loop'Nested Label-Goto 'loop' The following code outputs the numbers from 0 to 42:
func void foo() {\n var int count; count = 0;\n\n MEM_Label(0);\n /* <---- label now points here,\n * i.e. to the position AFTER the assignment of label. */\n\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n\n if (count <= 42) {\n // Jump to the MEM_Label\n MEM_Goto(0);\n };\n\n /* Once 43 is reached, the \u201cloop\u201d is exited. */\n};\n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n MEM_Label(0);\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n MEM_Label(1);\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n MEM_Goto(1);\n };\n x += 1;\n MEM_Goto(0);\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#while-loop","title":"While loop","text":"Ikarus also implements a while loop. Its syntax isn't as good as the loop from zParserExtender, due to the daedalus limitations, but it works as a normal while loop that can be found in many programming languages.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#syntax","title":"Syntax","text":"The Ikarus while loop consist of three things:
while function That works like a while statement and start of the brace while(var int b){
.
func void while(var int b)\n
end constant That works like an ending brace }
.
const int end = -72;\n
break and continue constant These two constants works like a regular break
and continue
statements in C.
const int break = -42;\nconst int continue = -23;\n
while loopfunc void while_test() {\n var int value; value = 10;\n while(value > 0); //{\n\n if (value == 8)\n {\n continue;\n };\n\n if (value == 2)\n {\n break;\n };\n end; //}\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_2","title":"Examples","text":"Simple while loopNested while loop The following code outputs the numbers from 0 to 42:
func void foo() {\n var int count; count = 0;\n while(count <= 42); //{\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n end; //}\n\n /* Once 43 is reached, the loop is exited. */\n}; \n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n while(x < max_x); //{\n y = 0;\n while(y < max_y); //{ \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n end; //}\n x += 1;\n end; //}\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#repeat-loop","title":"Repeat loop","text":"In addition Ikarus implements something called Repeat loop.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#initialization_1","title":"Initialization","text":"To use Repeat loop you must first call MEM_InitRepeat()
function once after loading a saved game. The recommended practice is to integrate this initialization function within INIT_GLOBAL
.
func void MEM_InitRepeat()\n
Tip
It's worth noting that MEM_InitRepeat
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#syntax_1","title":"Syntax","text":"Repeat loop has a syntax very similar to the while loop. It also uses end
constant as an ending brace. break
and continue
statements can be used within it as well. The main difference is the main loop function Repeat
that has following properties:
func void Repeat(var int variable, var int limit)\n
var int variable
A variable that increase with every loop iteration. var int limit
A variable that defines the number of loop iterations. If variable >= limit
the loop is exited. Repeat loop flowchart
flowchart TD\n A(Start) --> B[\"Repeat(i, limit)\"] \n B --> C{i < limit}\n C -->|true| D[Command]\n D --> |i = i + 1| B\n C --> |false| E(End)
Repeat loopfunc void Repeat_test() {\n Repeat(i, 4); var int i; //{\n MEM_Debug(IntToString(i));\n end; //}\n};\n\n// Results:\n// Info: 0 Q: Debug: 0\n// Info: 0 Q: Debug: 1\n// Info: 0 Q: Debug: 2\n// Info: 0 Q: Debug: 3\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_3","title":"Examples","text":"Simple Repeat loopNested Repeat loop The following code outputs the numbers from 0 to 42:
func void foo() {\n Repeat(count, 43); var int count; //{\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n end; //}\n\n /* Once 43 is reached, the loop is exited. */\n}; \n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n Repeat(x, max_x); //{\n y = 0;\n Repeat(y, max_y); //{ \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n end; //}\n end; //}\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/","title":"Keyboard interaction","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#keyboard-interaction","title":"Keyboard interaction","text":"This part of Ikarus implements function that make interaction with keyboard possible.
Info
Keyboard interaction is also implemented with gameKeyEvents.d
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#functions","title":"Functions","text":"Tip
Different players use different keys for specific actions! However, it is possible to get key assigned to the action from Gothic.ini. See Ini access.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_keypressed","title":"MEM_KeyPressed
","text":"MEM_KeyPressed
Checks if the key is hold right at the moment of function call.
func int MEM_KeyPressed(var int key)\n
Parameters Return value
The function returns TRUE
if the key is hold, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_keystate","title":"MEM_KeyState
","text":"MEM_KeyState
Returns the state of the key
.
func int MEM_KeyState(var int key)\n
Parameters Return value
The function returns actual key state.
Key states
KEY_UP
- The key is not pressed and was not pressed before. (\"not pressed\") KEY_PRESSED
- The key is pressed and was not previously pressed. (\"new pressed\") KEY_HOLD
- The key is pressed and was also pressed before. (\"still pressed\") KEY_RELEASED
- The key is not pressed and was previously pressed. (\"let go\") KEY_PRESSED
or KEY_RELEASED
will be returned if the state of the key has changed since the last query.
KEY_UP
or KEY_HOLD
are returned if the state has not changed.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_insertkeyevent","title":"MEM_InsertKeyEvent
","text":"MEM_InsertKeyEvent
Makes the game think that the key was pressed.
func void MEM_InsertKeyEvent(var int key)\n
Parameters var int key
Key to be \"pressed\" "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/","title":"Elementary memory access","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#elementary-memory-access","title":"Elementary memory access","text":"This part of Ikarus makes it possible to read and write memory as different data types - integers, strings, arrays of integers or strings and bytes.
If address <= 0
, an error is thrown. Otherwise, an attempt is made to read or write at this address. If the address falls into invalid range, for example in a code segment, access violation will occur (Gothic crashes). In the case of string operations, it is also necessary that at the specified position a valid zString already exists.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#read-functions","title":"Read functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readint","title":"MEM_ReadInt
","text":"MEM_ReadInt
Reads int from the address
.
func int MEM_ReadInt(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns an integer value if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readstring","title":"MEM_ReadString
","text":"MEM_ReadString
Reads string from the address
.
func string MEM_ReadString(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns string if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readbyte","title":"MEM_ReadByte
","text":"MEM_ReadByte
Reads byte from the address
.
func int MEM_ReadByte(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns byte value if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readintarray","title":"MEM_ReadIntArray
","text":"MEM_ReadIntArray
Reads int from the array at the arrayAddress
.
func int MEM_ReadIntArray(var int arrayAddress, var int offset)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns integer value from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readstringarray","title":"MEM_ReadStringArray
","text":"Info
MEM_ReadStringArray
has been already moved to the LeGo PermMem package.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readbytearray","title":"MEM_ReadByteArray
","text":"MEM_ReadByteArray
Reads byte from the array at the arrayAddress
.
func int MEM_ReadByteArray(var int arrayAddress, var int offset)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns byte from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#write-functions","title":"Write functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writeint","title":"MEM_WriteInt
","text":"MEM_WriteInt
Writes int value in the address
.
func void MEM_WriteInt(var int address, var int value)\n
Parameters var int address
Memory address to write into var int value
Integer value to write Example An example of using this function is the following Ikarus function, which turns debugging messages on and off:
func void MEM_SetShowDebug(var int on)\n{\n MEM_WriteInt(showDebugAddress, on);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writestring","title":"MEM_WriteString
","text":"MEM_WriteString
Writes string in the address
.
func void MEM_WriteString(var int address, var string value)\n
Parameters var int address
Memory address to write into var int value
String to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writebyte","title":"MEM_WriteByte
","text":"MEM_WriteByte
Only the byte at address address
is changed here, not a whole four-byte word. That is, the three subsequent bytes remain untouched. If 0 <= val < 256
does not apply in MEM_WriteByte
, a warning is issued and val is trimmed accordingly. In particular, shouldn't be negative numbers are passed.
func void MEM_WriteByte(var int address, var int value)\n
Parameters var int address
Memory address to write into var int value
Byte to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writeintarray","title":"MEM_WriteIntArray
","text":"MEM_WriteIntArray
Writes int value in the array at arrayAddress
.
func void MEM_WriteIntArray(var int arrayAddress, var int offset, var int value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var int value
Integer value to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writestringarray","title":"MEM_WriteStringArray
","text":"MEM_WriteStringArray
Writes string value in the array at arrayAddress
.
func void MEM_WriteStringArray(var int arrayAddress, var int offset, var string value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var string value
String to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writebytearray","title":"MEM_WriteByteArray
","text":"MEM_WriteByteArray
Writes byte value in the array at arrayAddress
.
func void MEM_WriteByteArray(var int arrayAddress, var int offset, var int value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var int value
Byte to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/","title":"Memory utility","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#memory-utility","title":"Memory utility","text":"Ikarus utility functions, for memory management and manipulation.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_alloc","title":"MEM_Alloc
","text":"MEM_Alloc
Allocates a specified amount of memory and returns a pointer to the allocated memory area.
Danger
Gothic does not and cannot retain a reference to this memory area or release it, even when destroying the session. Therefore, memory should only be reserved under certain conditions:
It is guaranteed to exist and can be released again with MEM_Free
after loading a save game. Gothic is aware of this memory area and independently releases it. It might be possible to create new objects with this function and permanently integrate them into the object structure of Gothic. However, extreme caution is advised, as object structures cannot be used, and manual handling is required.
This function is well-suited for building small elements like list items and integrating them into existing lists. The memory allocated by this function is always initialized to zero.
func int MEM_Alloc(var int amount)\n
Parameters var int amount
The amount of bytes to allocate Return value
The function returns a pointer to the allocated memory area.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_realloc","title":"MEM_Realloc
","text":"MEM_Realloc
Allocates a memory area of size newsize
and returns a pointer to this memory area. The memory area from location ptr
is released.
If newsize >= oldsize
, the first oldsize
bytes from the old memory area are transferred to the new one. The additional memory is initialized with zero.
If newsize <= oldsize
, all bytes of the new memory area are initialized with the corresponding values of the old memory area.
This function is intended to create an allocated memory area enlarge or reduce. Existing data remains naturally way received.
func int MEM_Realloc(var int ptr, var int oldsize, var int newsize)\n
Parameters var int ptr
The original pointer to the memory block var int oldsize
The size of the original memory block var int newsize
The size of the new memory block Return value
The function returns a pointer to the modified memory area.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_free","title":"MEM_Free
","text":"MEM_Free
Releases an allocated memory area.
Danger
Great caution is advised, especially when attempting to destroy engine objects, as no destructors are called!
Releasing small things such as list elements can be done easily.
func void MEM_Free(var int ptr)\n
Parameters var int ptr
Pointer to the released memory block "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copy","title":"MEM_Copy
","text":"MEM_Copy
Copies a specified number of words from the source address to the destination address.
func void MEM_Copy(var int src, var int dst, var int wordcount)\n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int wordCount
The number of words to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copywords","title":"MEM_CopyWords
","text":"MEM_CopyWords
Alias to MEM_Copy
. Copies a specified number of words from the source address to the destination address.
func void MEM_CopyWords(var int src, var int dst, var int wordcount) \n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int wordCount
The number of words to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copybytes","title":"MEM_CopyBytes
","text":"MEM_CopyBytes
Copies a specified number of bytes from the source address to the destination address
func void MEM_CopyBytes(var int src, var int dst, var int byteCount)\n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int byteCount
The number of bytes to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swap","title":"MEM_Swap
","text":"MEM_Swap
Swaps a specified number of words between the source address and the destination address.
func void MEM_Swap(var int src, var int dst, var int wordCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int wordCount
The number of words to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swapwords","title":"MEM_SwapWords
","text":"MEM_SwapWords
Alias to MEM_Swap
. Swaps a specified number of words between the source address and the destination address.
func void MEM_SwapWords(var int src, var int dst, var int wordCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int wordCount
The number of words to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swapbytes","title":"MEM_SwapBytes
","text":"MEM_SwapBytes
Swaps a specified number of bytes between the source address and the destination address.
func void MEM_SwapBytes(var int src, var int dst, var int byteCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int byteCount
The number of bytes to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_clear","title":"MEM_Clear
","text":"MEM_Clear
Sets a specified number of bytes in memory to zero.
func void MEM_Clear(var int ptr, var int size)\n
Parameters var int ptr
The memory address to start clearing from var int size
The number of bytes to clear "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_compare","title":"MEM_Compare
","text":"MEM_Compare
Compares a specified number of words between two memory blocks.
func int MEM_Compare(var int ptr0, var int ptr1, var int wordCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of words to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_comparewords","title":"MEM_CompareWords
","text":"MEM_CompareWords
Alias to MEM_Compare
. Compares a specified number of words between two memory blocks.
func int MEM_CompareWords(var int ptr0, var int ptr1, var int wordCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of words to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_comparebytes","title":"MEM_CompareBytes
","text":"MEM_CompareBytes
Compares a specified number of bytes between two memory blocks.
func int MEM_CompareBytes(var int ptr1, var int ptr2, var int byteCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of bytes to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/","title":"Access Menu Objects","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#access-menu-objects","title":"Access Menu Objects","text":"These Ikarus functions are intended to provide and simplify access to menu items (e.g. in the character menu).
Tip
Some menus are generated every time they are used, while others are generated once and then kept. For example, a character menu is only available after it was opened for the first time, after that it is kept in memory. Depending on what you actually want to do, it can make sense to introduce changes in the menu scripts.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#mem_getmenubystring","title":"MEM_GetMenuByString
","text":"MEM_GetMenuByString
func int MEM_GetMenuByString(var string menuName)\n
Parameters
var string menuName
Name of the Gothic menu e.g. MENU_STATUS
Return value
The function returns the address of the menu if a menu with this name exists, null otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#mem_getmenuitembystring","title":"MEM_GetMenuItemByString
","text":"MEM_GetMenuItemByString
func int MEM_GetMenuItemByString(var string menuItemName)\n
Parameters
var string menuItemName
Name of the Gothic menu item e.g. MENU_ITEM_PLAYERGUILD_TITLE
Return value
The function returns the address of the menu item if a menu item with this name exists, null otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/","title":"Ikarus `zCObject` manipulation functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#ikarus-zcobject-manipulation-functions","title":"Ikarus zCObject
manipulation functions","text":"Set of functions for working with zCObject
and its subclasses instances.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#global-instances","title":"Global instances","text":"Ikarus package introduces the following instances:
instance MEM_Game (oCGame);\ninstance MEM_World(oWorld);\ninstance MEM_Timer(zCTimer);\ninstance MEM_WorldTimer(oCWorldTimer);\ninstance MEM_Vobtree(zCTree);\ninstance MEM_InfoMan(oCInfoManager);\ninstance MEM_InformationMan (oCInformationManager);\ninstance MEM_Waynet(zCWaynet);\ninstance MEM_Camera(zCCamera);\ninstance MEM_SkyController(zCSkyController_Outdoor);\ninstance MEM_SpawnManager (oCSpawnManager);\ninstance MEM_GameMananger (CGameManager);\ninstance MEM_GameManager (CGameManager);\ninstance MEM_Parser(zCParser);\n
The classes used here all have one thing in common: there is a maximum of one object of them at the same time (e.g. there is not two worlds or two sky at the same time).
MEM_InitGlobalInst
function sets the offsets of these instances to the corresponding unique object. While it has been called, all of the above instances can be used.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_initglobalinst","title":"MEM_InitGlobalInst
","text":"MEM_InitGlobalInst
Initializes global instances of commonly used objects in the game (is called by the MEM_InitAll
function).
func void MEM_InitGlobalInst()\n
Warning
MEM_InitGlobalInst
must be executed once after loading a savegame. The easiest way is do it is to call this function from INIT_GLOBAL
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#functions","title":"Functions","text":"About zCClassDef For every class (derived from zCObject
) there is an \"administrative object\" of type zCClassDef
. This encapsulates some useful information about all objects in this class.
class zCClassDef {\n var string className; //zSTRING\n var string baseClassName; //zSTRING\n var string scriptClassName; //zSTRING\n var int baseClassDef; //zCClassDef*\n var int createNewInstance; //zCObject* ( *) (void) \n var int createNewInstanceBackup; //zCObject* ( *) (void)\n var int classFlags; //zDWORD\n var int classSize; //zDWORD\n var int numLivingObjects;\n var int numCtorCalled;\n var int hashTable; //zCObject**\n var int objectList_array; //zCObject**\n var int objectList_numAlloc; //int\n var int objectList_numInArray; //int\n var int bitfield;\n};\n
Full Ikarus definition of this class, with members description can be found in Misc.d
file. The class is same for G1 and G2A engines.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getclassdef","title":"MEM_GetClassDef
","text":"MEM_GetClassDef
Returns a pointer to the zCClassDef
of the object. For more info see the About zCClassDef section above.
Passing these functions a pointer that does not point to a zCObject will most likely result in a crash lead.
func int MEM_GetClassDef(var int objPtr)\n
Parameters var int objPtr
A pointer to the object whose class definition is to be retrieved Return value
The function returns a pointer to the zCClassDef
of the object.
Example This would return a pointer to the zCClassDef
object that belongs to the oCNpc
class.
func int example1\n{\n var int her; her = MEM_InstToPtr(hero);\n return MEM_GetClassDef(her);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getclassname","title":"MEM_GetClassName
","text":"MEM_GetClassName
This function returns the name of the class to which an object belongs.
func string MEM_GetClassName(var int objPtr)\n
Parameters var int objPtr
A pointer to the object whose class name is to be retrieved Return value
The function returns the objects class name as a string, if the object is invalid an empty string is returned.
Example This would return a name of the oCNpc
class as a string.
func string example2\n{\n var int her; her = MEM_InstToPtr(hero);\n return MEM_GetClassName(her);\n};\n// return: \"oCNpc\"\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_checkinheritance","title":"MEM_CheckInheritance
","text":"MEM_CheckInheritance
Checks if an object is derived from a specific class definition.
func int MEM_CheckInheritance(var int objPtr, var int classDef)\n
Parameters var int objPtr
A pointer to the object to be checked var int classDef
A pointer to the class definition to check against Return value
The function returns TRUE
if the object is derived from the specified class definition, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#hlp_is_","title":"Hlp_Is_*
","text":"Hlp_Is_*
In addition MEM_CheckInheritance
function has some overloads with hardcoded classDef
parameter.
func int Hlp_Is_oCMobFire(var int ptr){};\nfunc int Hlp_Is_zCMover(var int ptr){};\nfunc int Hlp_Is_oCMob(var int ptr){};\nfunc int Hlp_Is_oCMobInter(var int ptr){};\nfunc int Hlp_Is_oCMobLockable(var int ptr){};\nfunc int Hlp_Is_oCMobContainer(var int ptr){};\nfunc int Hlp_Is_oCMobDoor(var int ptr){};\nfunc int Hlp_Is_oCMobBed(var int ptr){};\nfunc int Hlp_Is_oCMobSwitch(var int ptr){};\nfunc int Hlp_Is_oCMobWheel(var int ptr){};\nfunc int Hlp_Is_oCMobLadder(var int ptr){};\nfunc int Hlp_Is_oCNpc(var int ptr){};\nfunc int Hlp_Is_oCItem(var int ptr){};\nfunc int Hlp_Is_zCVobLight(var int ptr){};\n
The usage of these functions is probably obvious, they checks if the given object belongs to class given in the function name.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_insertvob","title":"MEM_InsertVob
","text":"MEM_InsertVob
Inserts a Vob with the visual vis
at the waypoint wp
. If the visual or waypoint does not exist, this is the behaviour this function undefined.
Note
The inserted Vob is even an oCMob
, so it can be given a focus name, for example. But you can treat it like a zCVob
), if you don't need the additional properties.
func int MEM_InsertVob(var string vis, var string wp)\n
Parameters var string vis
Name of the inserted Vob visual (\"FAKESCROLL.3DS\"
, \"FIRE.PFX\"
, \"SNA_BODY.ASC\"
, \"CHESTSMALL_NW_POOR_LOCKED.MDS\"
, \"ADD_PIRATEFLAG.MMS\"
etc.) var string wp
Name of the waypoint to insert Vob on Return value
The function returns a pointer to the created object.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_deletevob","title":"MEM_DeleteVob
","text":"MEM_DeleteVob
Deletes a specific Vob form world.
func void MEM_DeleteVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to a zCVob
object to be deleted "},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_renamevob","title":"MEM_RenameVob
","text":"MEM_RenameVob
Renames the passed Vob to the newName
that is also passed.
The object becomes this first removed from the Vob-hashtable, then unnamed and then again inserted into the Vob-hashtable under a new name.
func void MEM_RenameVob(var int vobPtr, var string newName)\n
Parameters var int vobPtr
Pointer to a zCVob
object to be renamed var string newName
The new Name of the Vob MEM_TriggerVobMEM_UntriggerVob"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_triggervob","title":"MEM_TriggerVob
","text":"MEM_TriggerVob
Sends a trigger message to the Vob.
func void MEM_TriggerVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to a triggered zCVob
Danger
If triggering the Vob has immediate effects (even before MEM_TriggerVob is exited), the name of the Vob is corrupted during this time. It is not advisable to rename, trigger again or destroy the object at this moment, the behavior in such cases is untested.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_untriggervob","title":"MEM_UntriggerVob
","text":"MEM_UntriggerVob
Sends an untrigger message to the Vob.
func void MEM_TriggerVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to an untriggered zCVob
Danger
If untriggering the Vob has immediate effects (even before MEM_TriggerVob is exited), the name of the Vob is corrupted during this time. It is not advisable to rename, trigger again or destroy the object at this moment, the behavior in such cases is untested.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_searchvobbyname","title":"MEM_SearchVobByName
","text":"MEM_SearchVobByName
Returns the address of a zCVob
named str
if such a Vob exists.
func int MEM_SearchVobByName(var string str)\n
Parameters var string str
Name of searched zCVob
Return value
The function returns a pointer to the zCVob
if the object with the given name exist. 0
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_searchallvobsbyname","title":"MEM_SearchAllVobsByName
","text":"MEM_SearchAllVobsByName
Variation of MEM_SearchVobByName
. Creates a zCArray
in which all pointers are to Vobs with the name str
. If no Vob with the name exists, an empty zCArray
is created. A pointer to the created zCArray
is then returned. This can be evaluated, but should be released again with MEM_ArrayFree
before the end of the frame (before the player can load) to avoid memory leaks.
func int MEM_SearchAllVobsByName(var string str)\n
Parameters var string str
Name of searched zCVob
Return value
The function returns a pointer to the created zCArray
, that contains pointers to the all Vobs with the specified name.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getbuffercrc32","title":"MEM_GetBufferCRC32
","text":"MEM_GetBufferCRC32
Calculates the CRC32 hash value from a byte array starting at the address specified by buf
and having a length of buflen
.
func int MEM_GetBufferCRC32(var int buf, var int buflen)\n
Parameters var int buf
Address of a byte array, the hash calculation will begin from
var int buflen
The length of the byte array starting from the address specified by buf
Return value
The function returns the calculated CRC32 hash value.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getstringhash","title":"MEM_GetStringHash
","text":"MEM_GetStringHash
Calculates the CRC32 hash value for a string.
func int MEM_GetStringHash(var string str)\n
Parameters var string str
A string for which the hash value is to be calculated Return value
The function returns an integer representing the calculated hash value for the input string.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/","title":"`zCParser` related functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#zcparser-related-functions","title":"zCParser
related functions","text":"This Ikarus part provides some useful functions to work with parser, its instances, symbols and stack.
Danger
Remember to always assign an instance to a correct class. If you assign an oCNpc
pointer to oCItem
class you won't be able to read any data from it.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_reinitparser","title":"MEM_ReinitParser
","text":"MEM_ReinitParser
Parser operations are initialized with this function.
func void MEM_ReinitParser()\n
Tip
It's worth noting that MEM_ReinitParser
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#pointers-and-instances","title":"Pointers and instances","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_ptrtoinst","title":"MEM_PtrToInst
","text":"MEM_PtrToInst
Returns an instance pointed to by the pointer. If the pointer is null an error is thrown.
func MEMINT_HelperClass MEM_PtrToInst(var int ptr)\n
Parameters var int ptr
Pointer to return an instance from Shortcut
In addition there is a function _^
with the same signature and functionality as MEM_PtrToInst
. It is used as a shortcut, since the converting pointer to instance is commonly used while working with Ikarus.
func MEMINT_HelperClass _^ (var int ptr)\n
Example Following code
var oCNpc her; her = MEM_PtrToInst(heroPtr);\n
is equivalent to var oCNpc her; her = _^(heroPtr);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_nulltoinst","title":"MEM_NullToInst
","text":"MEM_NullToInst
Returns an instance from a null pointer.
func MEMINT_HelperClass MEM_NullToInst()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_assigninst","title":"MEM_AssignInst
","text":"MEM_AssignInst
Takes an instance from a pointer and assigns it to a given instance. If the pointer is null an error is thrown.
func void MEM_AssignInst(var int inst, var int ptr)\n
Parameters var int ptr
Pointer to assign an instance from var int inst
Instance to which the pointer will be assigned Example Following code
var oCNpc inst;\nMEM_AssignInst (inst, ptr); \n
is equivalent to var oCNpc inst;\ninst = MEM_PtrToInst(ptr);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_assigninstnull","title":"MEM_AssignInstNull
","text":"MEM_AssignInstNull
Assigns null pointer to a given instance.
func void MEM_AssignInstNull(var int inst)\n
Parameters var int inst
Instance to which the null pointer will be assigned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_insttoptr","title":"MEM_InstToPtr
","text":"MEM_InstToPtr
Returns a pointer to given instance.
func int MEM_InstToPtr(var int inst)\n
Parameters var int inst
The instance to which the pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_instgetoffset","title":"MEM_InstGetOffset
","text":"MEM_InstGetOffset
Alias to MEM_InstToPtr
. Returns a pointer to given instance.
func int MEM_InstGetOffset(var int inst)\n
Parameters var int inst
The instance to which the pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_cpyinst","title":"MEM_CpyInst
","text":"MEM_CpyInst
Returns a copy of a given instance
func MEMINT_HelperClass MEM_CpyInst(var int inst)\n
Parameters var int inst
Instance to copy example Following code
selfCopy = MEM_CpyInst (self);\n
is equivalent to selfCopy = MEM_PtrToInst (MEM_InstToPtr (self));\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#call-function","title":"Call function","text":"You don't always know at compile time when you want to call which function. For example, if you want to call the condition function of a mob that the player has in focus, you are at a loss at compile time because you have no idea which mob the player will choose. Ikarus provides a way to call functions based on their name or symbol index. In the example of the mob, the name of the condition function can simply be looked up in the mob.
Note
The functions below also work for externals without any restrictions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#passing-parameters","title":"Passing Parameters","text":"If the function to be called has parameters, these must first be placed on the data stack. The parameters must be pushed in the correct order, from left to right.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushintparam","title":"MEM_PushIntParam
","text":"MEM_PushIntParam
Passes an integer as a parameter to the called function.
func void MEM_PushIntParam (var int param)\n
Parameters var int param
Integer to pass as a function parameter "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushinstparam","title":"MEM_PushInstParam
","text":"MEM_PushInstParam
Passes an instance as a parameter to the called function.
func void MEM_PushInstParam (var int inst)\n
Parameters var int inst
Instance to pass as a function parameter "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushstringparam","title":"MEM_PushStringParam
","text":"!!! function \"`MEM_PushStringParam`\"\nPasses a string as a parameter to the called function.\n```dae\nfunc void MEM_PushStringParam (var string str)\n```\n**Parameters**\n\n- `#!dae var string str` \n String to pass as a function parameter\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#the-call","title":"The call","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_call","title":"MEM_Call
","text":"MEM_Call
Calls a function.
func void MEM_Call(var func fnc)\n
Parameters var func fnc
Function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyid","title":"MEM_CallByID
","text":"MEM_CallByID
Calls a function by its ID.
func void MEM_CallByID (var int symbID)\n
Parameters var int symbID
The ID of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyptr","title":"MEM_CallByPtr
","text":"MEM_CallByPtr
Calls a function by its pointer.
func void MEM_CallByPtr(var int ptr)\n
Parameters var int ptr
The pointer of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyoffset","title":"MEM_CallByOffset
","text":"MEM_CallByOffset
Calls a function by its offset.
func void MEM_CallByOffset(var int offset)\n
Parameters var int offset
The offset of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbystring","title":"MEM_CallByString
","text":"MEM_CallByString
Calls a function by its name.
func void MEM_CallByString (var string fnc)\n
Parameters var string fnc
The name of the function IN CAPITAL LETTERS. "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#return-value","title":"Return value","text":"If a function has a return value, it should be fetched from the data stack after it is called, otherwise stack overflows can occur under unfavorable circumstances (aside from that, you may simply want the return value because it contains important information).
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popintresult","title":"MEM_PopIntResult
","text":"MEM_PopIntResult
Retrieves an integer returned by the called function.
func int MEM_PopIntResult()\n
Return value The function returns an integer returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popstringresult","title":"MEM_PopStringResult
","text":"MEM_PopStringResult
Retrieves a daedalus string returned by the called function.
func string MEM_PopStringResult()\n
Return value The function returns a string returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popinstresult","title":"MEM_PopInstResult
","text":"MEM_PopInstResult
Retrieves an instance returned by the called function.
func MEMINT_HelperClass MEM_PopInstResult()\n
Return value The function returns an instance returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#function-stuff","title":"Function stuff","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncid","title":"MEM_GetFuncID
","text":"MEM_GetFuncID
Returns the ID of the given function.
func int MEM_GetFuncID(var func fnc)\n
Parameters var func fnc
The function whose ID is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncptr","title":"MEM_GetFuncPtr
","text":"MEM_GetFuncPtr
Returns the pointer of the given function.
func int MEM_GetFuncPtr(var func fnc)\n
Parameters var func fnc
The function whose pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncoffset","title":"MEM_GetFuncOffset
","text":"MEM_GetFuncOffset
Returns the offset of the given function.
func int MEM_GetFuncOffset(var func fnc)\n
Parameters var func fnc
The function whose offset is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncidbyoffset","title":"MEM_GetFuncIDByOffset
","text":"MEM_GetFuncIDByOffset
MEM_GetFuncID
, but with an offset as a parameter.
func int MEM_GetFuncIDByOffset(var int offset)\n
Parameters var int offset
Offset of a function whose ID is returned Return value
The function returns an ID of a function with a given offset.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_replacefunc","title":"MEM_ReplaceFunc
","text":"MEM_ReplaceFunc
Replaces the f1
function with f2
function so if you call the first function, the second function is called.
func void MEM_ReplaceFunc(var func f1, var func f2)\n
Parameters var func f1
Function to replace var func f2
Function called instead of f1
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#parser-stack","title":"Parser stack","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getframeboundary","title":"MEM_GetFrameBoundary
","text":"MEM_GetFrameBoundary
Returns the address/pointer to the boundary of a stack frame (ESP).
func int MEM_GetFrameBoundary()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getcallerstackpos","title":"MEM_GetCallerStackPos
","text":"MEM_GetCallerStackPos
Retrieves the stack position (pop position) of the caller's caller (look at the example for better understanding).
func int MEM_GetCallerStackPos()\n
Return value The function returns an integer representing the stack position of the caller's caller.
Example After calling B()
from within A()
, when MEM_GetCallerStackPos()
is invoked in function B()
, it retrieves the stack position of the caller's caller, which is function A()
in this case. Therefore, the variable adr
will contain the stack position of function A()
.
func void A(){\n B();\n};\n\nfunc void B(){\n int adr; adr = MEM_GetCallerStackPos();\n // Now, 'adr' will contain the stack position of A.\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_setcallerstackpos","title":"MEM_SetCallerStackPos
","text":"MEM_SetCallerStackPos
Sets the stack position (pop position) of the caller's caller.
func void MEM_SetCallerStackPos(var int popPos)\n
Parameters var int popPos
An integer parameter representing the new stack position of the caller's caller "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#get-address","title":"Get address","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getaddress_init","title":"MEM_GetAddress_Init
","text":"MEM_GetAddress_Init
Initializes the MEM_GetIntAddress
, MEM_GetFloatAddress
and MEM_GetStringAddress
functions.
func void MEM_GetAddress_Init()\n
Tip
It's worth noting that MEM_GetAddress_Init
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getintaddress","title":"MEM_GetIntAddress
","text":"MEM_GetIntAddress
Returns an address of a given integer.
func int MEM_GetIntAddress(var int i)\n
Parameters var int i
Integer whose address is returned Shortcut
In addition there is a function _@
with the same signature and functionality as MEM_GetIntAddress
.
func int _@(var int i)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfloataddress","title":"MEM_GetFloatAddress
","text":"MEM_GetFloatAddress
Returns an address of a given daedalus float.
func int MEM_GetFloatAddress(var float f)\n
Parameters var float f
Float whose address is returned Shortcut
In addition there is a function _@f
with the same signature and functionality as MEM_GetFloatAddress
.
func int _@s(var string s)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getstringaddress","title":"MEM_GetStringAddress
","text":"MEM_GetStringAddress
Returns an address of a given string.
func int MEM_GetStringAddress(var string s)\n
Parameters var string s
String whose address is returned Shortcut
In addition there is a function _@s
with the same signature and functionality as MEM_GetStringAddress
.
func int _@s(var string s)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#str_getaddressinit","title":"STR_GetAddressInit
","text":"STR_GetAddressInit
Alias to MEM_GetAddress_Init
, kept for downward compatibility.
func void STR_GetAddressInit()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#str_getaddress","title":"STR_GetAddress
","text":"STR_GetAddress
Function similar to MEM_GetStringAddress
. There is a guarantee, that this function works initialized i.e. invokes MEM_GetAddress_Init
, but the first time may only return an address of a copy of the string.
func int STR_GetAddress(var string str)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#static-arrays","title":"Static arrays","text":"Accessing static arrays like this below is very tedious in Daedalus.
var int myStaticArray[42];\n
It is not possible to access myStaticArray[i]
with a variable index i, but only with a constant. This changes with the following functions. Danger
Neither function performs any kind of validity check. If the value passed is not an array or offsets are beyond the boundaries of the array passed, the behavior is undefined.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_initstatarrs","title":"MEM_InitStatArrs
","text":"MEM_InitStatArrs
Initializes static arrays read and write functions.
func void MEM_InitStatArrs()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_writestatarr","title":"MEM_WriteStatArr
","text":"MEM_WriteStatArr
Changes the value at the offset
of a static integer-array.
func void MEM_WriteStatArr (var int array, var int offset, var int value)\n
Parameters var int array
Array which will be edited var int offset
Array index at which value will be edited var int value
The new value "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_readstatarr","title":"MEM_ReadStatArr
","text":"MEM_ReadStatArr
Reads the value at the specific offset of a static integer-array.
func int MEM_ReadStatArr (var int array, var int offset)\n
Parameters var int array
Array to get a value from var int offset
Array index of the value to return Return value
The function returns an integer value from the offset
of a given static array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_writestatstringarr","title":"MEM_WriteStatStringArr
","text":"MEM_WriteStatStringArr
Changes the value at the offset
of a static string-array.
func void MEM_WriteStatStringArr(var string array, var int offset, var string value)\n
Parameters var string array
Array which will be edited var int offset
Array index at which value will be edited var string value
The new value "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_readstatstringarr","title":"MEM_ReadStatStringArr
","text":"MEM_ReadStatStringArr
Reads the value at the specific offset of a static string-array.
func string MEM_ReadStatStringArr(var string array, var int offset)\n
Parameters var string array
Array to get a value from var int offset
Array index of the value to return Return value
The function returns a string form the offset
of a given static array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#parser-symbol","title":"Parser symbol","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_setcurrparsersymb","title":"MEM_SetCurrParserSymb
","text":"MEM_SetCurrParserSymb
Makes currParserSymb
point to the symbol of the specified instance.
func void MEM_SetCurrParserSymb (var int inst)\n
Parameters var int inst
Instance to whose symbol currParserSymb
will be set "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#currparsersymb","title":"currParserSymb
","text":"currParserSymb
An instance representing current parser symbol.
INSTANCE currParserSymb (zCPar_Symbol);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_findparsersymbol","title":"MEM_FindParserSymbol
","text":"MEM_FindParserSymbol
Returns the index of the parser symbol with name inst
if such a symbol exists.
func int MEM_FindParserSymbol(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the index of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbolindex","title":"MEM_GetSymbolIndex
","text":"MEM_GetSymbolIndex
Alias to MEM_FindParserSymbol
. Returns the index of the parser symbol with name inst
if such a symbol exists.
func int MEM_GetSymbolIndex(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the index of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getparsersymbol","title":"MEM_GetParserSymbol
","text":"MEM_GetParserSymbol
Looks for the parser symbol with the name inst
and returns a pointer to the appropriate zCPar_Symbol
structure.
func int MEM_GetParserSymbol (var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbol","title":"MEM_GetSymbol
","text":"MEM_GetSymbol
Alias to MEM_GetParserSymbol
. Looks for the parser symbol with the name inst
and returns a pointer to the appropriate zCPar_Symbol
structure.
func int MEM_GetSymbol(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbolbyindex","title":"MEM_GetSymbolByIndex
","text":"MEM_GetSymbolByIndex
MEM_GetParserSymbol
, but with ID (index) as a parameter.
func int MEM_GetSymbolByIndex(var int id)\n
Parameters var string inst
ID (index) of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/","title":"String operations","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/string/#string-operations","title":"String operations","text":"Collection of Ikarus functions to manipulate and format strings.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_getcharat","title":"STR_GetCharAt
","text":"STR_GetCharAt
Returns the ASCII value of a character at a specific position in a string.
func int STR_GetCharAt (var string str, var int pos)\n
Parameters var string str
The input string var int pos
The position of the character Return value
The function returns the ASCII value of the character at the specified position.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_len","title":"STR_Len
","text":"STR_Len
Returns the length of a string.
func int STR_Len (var string str)\n
Parameters var string str
The input string Return value
The function returns the length of the string in characters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_tochar","title":"STR_toChar
","text":"STR_toChar
Converts a string to a pointer to its character array.
func int STR_toChar (var string str)\n
Parameters var string str
The input string Return value
The function returns a pointer to the character array representing the input string str
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_fromchar","title":"STR_FromChar
","text":"STR_FromChar
Converts a character array to a string.
func string STR_FromChar(var int char)\n
Parameters var int char
Pointer to the character array Return value
The function returns a string representation of the character array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_substr","title":"STR_SubStr
","text":"STR_SubStr
Extracts a substring from a given string.
func string STR_SubStr (var string str, var int start, var int count)\n
Parameters var string str
The input string var int start
The starting position of the substring var int count
The length of the substring Return value
The function returns a substring, if the starting position is invalid an empty string is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_prefix","title":"STR_Prefix
","text":"STR_Prefix
Extracts a prefix of a given string, similar to STR_SubStr
, but with the starting position set to the first character of the string.
func string STR_Prefix (var string str, var int len)\n
Parameters var string str
The input string var int count
The length of the prefix Return value
The function returns a prefix of the input string with the specified length.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_compare","title":"STR_Compare
","text":"STR_Compare
Compares two strings lexicographically and returns a result indicating their relative order.
func int STR_Compare(var string str1, var string str2)\n
Parameters var string str1
The first string to compare var string str2
The second string to compare Return Value
The function returns an integer value representing the result of the comparison:
STR_GREATER
(1): If str1
comes lexicographically after str2
. STR_EQUAL
(0): If str1
is lexicographically equal to str2
. STR_SMALLER
(-1): If str1
comes lexicographically before str2
. Examples The comparison is based on lexicographic order, which is the order of characters as they appear in the ASCII table. Uppercase letters come before lowercase letters.
int result1 = STR_Compare(\"A\", \"B\");\n// The 'result1' variable now contains STR_SMALLER\n\nint result2 = STR_Compare(\"ABC\", \"ABC\");\n// The 'result2' variable now contains STR_EQUAL\n\nint result3 = STR_Compare(\"AA\", \"A\");\n// The 'result3' variable now contains STR_GREATER\n\nint result4 = STR_Compare(\"BA\", \"BB\");\n// The 'result4' variable now contains STR_SMALLER\n\nint result5 = STR_Compare(\"B\", \"a\");\n// The 'result5' variable now contains STR_SMALLER\n\nint result6 = STR_Compare(\"A\", \"\");\n// The 'result6' variable now contains STR_GREATER\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_toint","title":"STR_ToInt
","text":"STR_ToInt
Converts a string to an integer.
func int STR_ToInt (var string str)\n
Parameters var string str
The input string Return Value
The function returns an integer value of the string, if a string is invalid (doesn't contain an integer) zero is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_indexof","title":"STR_IndexOf
","text":"STR_IndexOf
Searches for a substring tok
within a given string and returns the index of the first occurrence of tok
, taking into account upper and lower case letters.
func int STR_IndexOf(var string str, var string tok)\n
Parameters var string str
The string in which to search for tok
. var string tok
The substring to search for within str
. Return Value
The function returns the index at which the first occurrence of tok
begins within str
. If tok
is not found in str
, the function returns -1.
Examples int index1 = STR_IndexOf(\"Hello World!\", \"Hell\");\n// The 'index1' variable now contains 0\n\nint index2 = STR_IndexOf(\"Hello World!\", \"World\");\n// The 'index2' variable now contains 6\n\nint index3 = STR_IndexOf(\"Hello World!\", \"Cake\");\n// The 'index3' variable now contains -1\n\nint index4 = STR_IndexOf(\"Hello World!\", \"\");\n// The 'index4' variable now contains 0\n\nint index5 = STR_IndexOf(\"Hello\", \"Hello World!\");\n// The 'index5' variable now contains -1\n\nint index6 = STR_IndexOf(\"hello Hell!\", \"Hell\");\n// The 'index6' variable now contains 6\n\nint index7 = STR_IndexOf(\"\", \"\");\n// The 'index7' variable now contains 0\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_splitcount","title":"STR_SplitCount
","text":"STR_SplitCount
Counts the number of parts a string splits into when using a specified separator.
func int STR_SplitCount(var string str, var string separator)\n
Parameters var string str
The input string to be split. var string separator
The separator character or string used to split the input string. Return Value
The function returns a number of parts the input string splits into when using the specified separator.
Example string inputStr = \"This is a sentence.\";\nint count = STR_SplitCount(inputStr, \" \");\n// The 'count' variable now contains 4\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_split","title":"STR_Split
","text":"STR_Split
Splits a string into multiple substrings based on a specified separator and returns the substring at a specified offset.
func string STR_Split(var string str, var string separator, var int offset)\n
Parameters
var string str
The input string to be split. var string separator
The separator character or string used to split the input string. var int offset
The index of the substring to be returned after splitting. The index is zero-based. Return Value
The function returns a substring at the specified offset after splitting the input string. If the offset is greater than or equal to the number of parts generated by splitting, an empty string is returned.
Example
func void foo() {\n string inputStr = \"This is a sentence.\";\n string tok1 = STR_Split(inputStr, \" \", 0); // This\n string tok2 = STR_Split(inputStr, \" \", 1); // is\n string tok3 = STR_Split(inputStr, \" \", 2); // a\n string tok4 = STR_Split(inputStr, \" \", 3); // sentence\n};\n
At the end of the function, tok1
contains \"This\", tok2
contains \"is\", tok3
contains \"a\", and tok4
contains \"sentence.\"."},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_upper","title":"STR_Upper
","text":"STR_Upper
Converts a string to uppercase.
func string STR_Upper(var string str)\n
Parameters var string str
The input string Return Value
The function returns a copy of str
with all uppercase letters converted to their corresponding uppercase letters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_lower","title":"STR_Lower
","text":"STR_Lower
Converts a string to lowercase.
func string STR_Lower(var string str)\n
Parameters var string str
The input string Return Value
The function returns a copy of str
with all lowercase letters converted to their corresponding uppercase letters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/","title":"Time and Benchmark","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#time-and-benchmark","title":"Time and Benchmark","text":"Set of functions to time measurement and Benchmark.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#time-functions","title":"Time functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_getsystemtime","title":"MEM_GetSystemTime
","text":"MEM_GetSystemTime
Returns the elapsed time since Gothic started.
func int MEM_GetSystemTime()\n
Return value The function returns the elapsed time since the start of Gothic in milliseconds. This value is used for timing measurements, in the BenchmarkMS
functions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_getperformancecounter","title":"MEM_GetPerformanceCounter
","text":"MEM_GetPerformanceCounter
Call to the WinAPI QueryPerformanceCounter
function.
func int MEM_GetPerformanceCounter()\n
Return value The function returns a value representing the number of elapsed ticks since the system was started. This value is used for timing measurements, in the BenchmarkPC
functions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#benchmark-functions","title":"Benchmark functions","text":"Tip
For reliable results, avoid measuring a single run of a function; instead, measure the total duration of multiple runs (e.g., 1000). This is crucial, especially for very fast functions, as a single run can distort the measurement. Use _N
benchmark functions to include a parameter specifying the number of runs for function f
.
Choose the parameter n
to ensure meaningful results. If n
executions take less than a millisecond, obtaining a return value in milliseconds has no sense. For very fast functions, the time spent in the benchmark function, not in f
, significantly affects the measurement, falsifying the result. Reliable measurements are achievable only for functions with sufficient slowness.
For reference, here is a timing for some operations (in nanoseconds, i.e., billionths of a second):
- Function call (jumping back and forth): 30ns\n- Elementary calculation (e.g., i = i + 1): 130ns\n- Wld_IsTime: 200ns\n- MEM_ReadInt, MEM_WriteInt: 350ns\n- Hlp_StrCmp(\"Hello\", \"Hello\"): 500ns\n- MEM_InstToPtr: 1400ns\n- (small) Allocate and free memory: 9700ns\n- CALL__stdcall (in empty function): 29000ns\n- MEM_GetParserSymb: 280000ns\n\n- Iteration of the benchmark function: 300ns\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkms","title":"MEM_BenchmarkMS
","text":"MEM_BenchmarkMS
Benchmark of the execution time for a specified function. (Milliseconds)
func int MEM_BenchmarkMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the duration of a function execution in milliseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkmms","title":"MEM_BenchmarkMMS
","text":"MEM_BenchmarkMMS
Benchmark of the execution time for a specified function. (microseconds)
func int MEM_BenchmarkMMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the duration of a function execution in microseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkpc","title":"MEM_BenchmarkPC
","text":"MEM_BenchmarkPC
Benchmark of the execution time for a specified function, using the Performancecounter.
func int MEM_BenchmarkMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the number of Performancecounter ticks the function needs.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkms_n","title":"MEM_BenchmarkMS_N
","text":"MEM_BenchmarkMS_N
MEM_BenchmarkMS
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkMS_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed duration of multiple (n
) runs of the function in milliseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkmms_n","title":"MEM_BenchmarkMMS_N
","text":"MEM_BenchmarkMMS_N
MEM_BenchmarkMMS
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkMMS_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed duration of multiple (n
) runs of the function in microseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkpc_n","title":"MEM_BenchmarkPC_N
","text":"MEM_BenchmarkPC_N
MEM_BenchmarkPC
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkPC_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed number of Performancecounter ticks needed to execute function multiple (n
) times.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/","title":"Windows Utilities","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#windows-utilities","title":"Windows Utilities","text":"This part of Ikarus implements some WinAPI functions that can be used directly from Gothic scripts.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#loadlibrary","title":"LoadLibrary
","text":"LoadLibrary
Loads the specified module into the address space of the calling process. Full documentation here.
func int LoadLibrary(var string lpFileName)\n
Parameters var string lpFileName
Name of loaded module Return value
The function returns a handle to the module.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#getprocaddress","title":"GetProcAddress
","text":"GetProcAddress
Retrieves the address from the specified dynamic-link library. Full documentation here.
func int GetProcAddress(var int hModule, var string lpProcName)\n
Parameters var int hModule
A handle to the DLL module that contains the function or variable. Can be obtained using the LoadLibrary
function. var string lpProcName
The function or variable name. Return value The function returns address of the function or variable.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#findkerneldllfunction","title":"FindKernelDllFunction
","text":"FindKernelDllFunction
Uses GetProcAddress
to find function inside the KERNEL32.DLL
file.
func int FindKernelDllFunction(var string name)\n
Parameters var string name
Name of the looked function. Return value
The function returns address of the function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#virtualprotect","title":"VirtualProtect
","text":"VirtualProtect
Changes the protection on a region of committed pages in the virtual address space of the calling process. Full documentation here.
func int VirtualProtect(var int lpAddress, var int dwSize, var int flNewProtect)\n
Parameters var int lpAddress
The address of the starting page of the region of pages whose access protection attributes are to be changed. var int dwSize
The size of the region whose access protection attributes are to be changed, in bytes. var int flNewProtect
The memory protection option. All options can be found here. Return value
The function returns lpflOldProtectPtr
- a pointer to a variable that receives the previous access protection value.
Author's comment:
I made lpflOldProtectPtr
the return value and ignored the return Value of VirtualProtect.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#memoryprotectionoverride","title":"MemoryProtectionOverride
","text":"MemoryProtectionOverride
Alias to VirtualProtect
but with predefined PAGE_EXECUTE_READWRITE
protection option
func void MemoryProtectionOverride(var int address, var int size)\n
Parameters var int address
The address of the starting page of the region of pages whose access protection attributes are to be changed. var int size
The size of the region whose access protection attributes are to be changed, in bytes. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#mem_messagebox","title":"MEM_MessageBox
","text":"MEM_MessageBox
Calls the WinAPI MessageBox function.
func int MEM_MessageBox(var string txt, var string caption, var int type)\n
Parameters var string txt
Content of the MessageBox. var string caption
Header of MessageBox. var int type
Type of MessageBox. All types listed here. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#mem_infobox","title":"MEM_InfoBox
","text":"MEM_InfoBox
Alias to MEM_MessageBox
with \"Information:\" header and MB_OK | MB_ICONINFORMATION
type.
func void MEM_InfoBox(var string txt)\n
Parameters var string txt
Content of the InfoBox. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#sleep","title":"Sleep
","text":"Following function calls the Sleep
function from the KERNEL32.DLL
. A documentation of this function can be found here.
func void Sleep(var int ms) {\n var int adr;\n adr = GetProcAddress(LoadLibrary(\"KERNEL32.DLL\"), \"Sleep\");\n\n CALL_IntParam(ms);\n CALL__stdcall(adr); // 0x007B47E6\n};\n
"},{"location":"zengin/scripts/extenders/lego/","title":"LeGo","text":""},{"location":"zengin/scripts/extenders/lego/#lego","title":"LeGo","text":"LeGo (LehonaGottfried) is a script packet built on top of Ikarus.
Contacts Author Lehona, Gottfried & contributors GitHub LeGo Forum LeGo Note
The code for LeGo is hosted on GitHub and LeGo has its very own documentation page.
"},{"location":"zengin/scripts/extenders/lego/setup/","title":"LeGo Setup","text":""},{"location":"zengin/scripts/extenders/lego/setup/#lego-setup","title":"LeGo Setup","text":"Danger
LeGo depends on Ikarus script packet, if you didn't install it yet check the Ikarus Setup. This guide assumes that you already have Ikarus running.
"},{"location":"zengin/scripts/extenders/lego/setup/#download","title":"Download","text":"First you need to download LeGo from the official github repository. We recommend using the dev
branch as it contains the latest and most up-to-date version of the package. However, you can also download a specific release if needed.
"},{"location":"zengin/scripts/extenders/lego/setup/#file-location","title":"File location","text":"If you followed the Ikarus Setup guide you probably have a \"MOD\" (or any other named) folder inside the <Gothic-dir>\\_work\\Data\\Scripts\\Content
directory. If not create it.
Unpack the downloaded files into this folder. The archiver should create a folder named LeGo-dev
or LeGo-X.X.X
. For better readability change its name to just LeGo
.
Tip
It's a good practice to delete any unused files, so delete files for other gothic version than this you are using.
"},{"location":"zengin/scripts/extenders/lego/setup/#parsing","title":"Parsing","text":"LeGo has a special header files, one for each supported engine version. All you need to do is to include them in Gothic.src
right after the Ikarus files.
Gothic.src (G1)Gothic.src (G2) _INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G1.SRC\nMOD\\LEGO\\HEADER_G1.SRC\n
_INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G2.SRC\nMOD\\LEGO\\HEADER_G2.SRC\n
"},{"location":"zengin/scripts/extenders/lego/setup/#initialization","title":"Initialization","text":"Before you can use LeGo and its packages, it must be properly initialized.
Warning
Gothic 1 by default doesn't have its own INIT_GLOBAL
function inside Startup.d
file. If you haven't created it yet see how to do it here.
You initialize LeGo by calling the LeGo_Init(var int flags)
function and specifying the flags.
Init AllExclude packagesInit specific packages With LeGo_All
flag you initialize all packages, excluding experimental Buffs and Render.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_All)\n};\n
By the bitwise NOT
operator you can exclude specific packages from LeGo_All
flag.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_All &~ (LeGo_Focusnames | LeGo_Bloodsplats));\n};\n
You could also init specific packages with bitwise OR
.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_AI_Function | LeGo_Saves);\n};\n
"},{"location":"zengin/scripts/extenders/lego/userconstants/","title":"User constants","text":""},{"location":"zengin/scripts/extenders/lego/userconstants/#user-constants","title":"User constants","text":"All constants that the user can either use or even change freely are defined in Userconst.d file.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#read-only","title":"Read only","text":"These constants may only be used, not changed.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#anim8","title":"Anim8","text":"These constants are used by Anim8 and Anim8q.
const int A8_Constant
Constant movement speed const int A8_SlowEnd
Evenly decelerated movement const int A8_SlowStart
Evenly accelerated movement const int A8_Wait
Do nothing. The target value is ignored here "},{"location":"zengin/scripts/extenders/lego/userconstants/#buttons","title":"Buttons","text":"The following bit masks can be applied to the status of a button:
const int BUTTON_ACTIVE
The button is active, it reacts to the mouse const int BUTTON_ENTERED
The mouse is \"within\" the button "},{"location":"zengin/scripts/extenders/lego/userconstants/#interface","title":"Interface","text":"Dimensions
const int PS_X
and const int PS_Y
Use with Print_Screen
or Print_ToVirtual
functions const int PS_VMax
Highest possible value of a virtual coordinate Colors
16 basic colors that can be used as zColor
parameters
const int COL_Aqua
const int COL_Black
const int COL_Blue
const int COL_Fuchsia
const int COL_Gray
const int COL_Green
const int COL_Lime
const int COL_Maroon
const int COL_Navy
const int COL_Olive
const int COL_Purple
const int COL_Red
const int COL_Silver
const int COL_Teal
const int COL_White
const int COL_Yellow
"},{"location":"zengin/scripts/extenders/lego/userconstants/#gamestate","title":"Gamestate","text":"Gamestate can assume these values:
const int Gamestate_NewGame
New game started const int Gamestate_Loaded
A game has been loaded const int Gamestate_WorldChange
The world has changed const int Gamestate_Saving
The game is saved "},{"location":"zengin/scripts/extenders/lego/userconstants/#cursor","title":"Cursor","text":"These constants are sent with Cursor_Event
:
const int CUR_LeftClick
The left mouse button was pressed const int CUR_RightClick
The right mouse button was pressed const int CUR_MidClick
The middle mouse button was pressed const int CUR_WheelUp
Mouse wheel up const int CUR_WheelDown
Mouse wheel down "},{"location":"zengin/scripts/extenders/lego/userconstants/#modifiable","title":"Modifiable","text":"These constants are often used by packages and may be changed freely.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#bloodsplats","title":"Bloodsplats","text":" const int BLOODSPLAT_NUM
Maximum number on screen const int BLOODSPLAT_TEX
Highest Texture ID (\"BLOODSPLAT\" + texID + \".TGA\"
) const int BLOODSPLAT_DAM
Texture size damage multiplier (damage * 2
Bloodsplat_Dam
) "},{"location":"zengin/scripts/extenders/lego/userconstants/#cursor_1","title":"Cursor","text":" const string Cursor_Texture
This texture is used to display the cursor (default: \"CURSOR.TGA\") "},{"location":"zengin/scripts/extenders/lego/userconstants/#interface_1","title":"Interface","text":" const string Print_LineSeperator
Text boxes can be printed in multiple lines. This character separates the lines from each other. "},{"location":"zengin/scripts/extenders/lego/userconstants/#prints","title":"PrintS","text":"All position and size information is completely virtual:
const int PF_PrintX
Start position on the X axis const int PF_PrintY
Start position on the Y axis const int PF_TextHeight
Space between individual lines The times are given in ms:
const int PF_FadeInTime
Time to fade in the text const int PF_FadeOutTime
Time to fade out the text const int PF_MoveYTime
Time needed to \"slip down\" const int PF_WaitTime
Time during which the print is fully visible The font can be modified:
const string PF_Font
Default: FONT_OLD_10_WHITE.TGA
"},{"location":"zengin/scripts/extenders/lego/userconstants/#talents","title":"Talents","text":" const int AIV_TALENT
Used AIVar "},{"location":"zengin/scripts/extenders/lego/userconstants/#dialoggestures","title":"Dialoggestures","text":" const string DIAG_Prefix
Animation prefix (\"DG_\") const string DIAG_Suffix
Animation suffix (\"_\") "},{"location":"zengin/scripts/extenders/lego/applications/anim8/","title":"Anim8","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8","title":"Anim8","text":"Info
Dependencies: - Floats Implementation: Anim8.d on GitHub
This package allows int or float values to be \"animated\" over a period of time. It is possible to string several commands together and to set the type of movement. The new version of PrintS
from Interface uses Anim8.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#initialization","title":"Initialization","text":"Initialize with LeGo_Anim8
flag.
LeGo_Init(LeGo_Anim8);\n
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_new","title":"Anim8_New
","text":"Anim8_New
Creates a new Anim8 object that can be filled with commands.
func int Anim8_New(var int initialValue, var int IsFloat)\n
Parameters var int initialValue
The initial value to start animating from. Can be an integer, or an Ikarus float. var int IsFloat
If the initialValue
is an Ikarus float, this parameter must be set to TRUE
. If it is an integer, it must be set to FALSE
. Return value
The function returns handle of the Anim8 object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_newext","title":"Anim8_NewExt
","text":"Anim8_NewExt
Creates a new Anim8 object with advanced options. Extends the Anim8_New
function.
func int Anim8_NewExt(var int value, var func handler, var int data, var int IsFloat)\n
Parameters var int value
The initial value to start animating from. Can be an integer, or an Ikarus float. var func handler
This function is called whenever the object is updated. The signature of the functions depends on the data
value: data != 0
: func void handler(var int data, var int value)
, data == 0
: func void handler(var int value)
. var int data
Optional parameter to send an additional value to the handler
function. If data == 0
, it is ignored. var int IsFloat
If the initialValue
is an Ikarus float, this parameter must be set to TRUE
. If it is an integer, it must be set to FALSE
. Return value
The function returns handle of the Anim8 object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_delete","title":"Anim8_Delete
","text":"Anim8_Delete
Deletes an Anim8 object created with Anim8_New
.
func void Anim8_Delete(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_get","title":"Anim8_Get
","text":"Anim8_Get
Get current value of the object.
func int Anim8_Get(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
Return value
The function returns value of the object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_set","title":"Anim8_Set
","text":"Anim8_Set
Sets the value of the object.
func void Anim8_Set(var int handle, var int value)\n
Parameters var int handle
Handle returned from Anim8_New
var int value
New value of the object "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_empty","title":"Anim8_Empty
","text":"Anim8_Empty
Indicates whether the object is empty, i.e. has no more commands to process.
func int Anim8_Empty(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
Return value
The function returns TRUE
if object is empty (has no more commands), FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_removeifempty","title":"Anim8_RemoveIfEmpty
","text":"Anim8_RemoveIfEmpty
If desired, Anim8 can automatically delete an object after it is empty.
func void Anim8_RemoveIfEmpty(var int handle, var int on)\n
Parameters var int handle
Handle returned from Anim8_New
var int on
TRUE
: enable, FALSE
: disable "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_removedataifempty","title":"Anim8_RemoveDataIfEmpty
","text":"Anim8_RemoveDataIfEmpty
With Anim8_NewExt
handler and data can be set. If this function is called with TRUE
, data
is taken as a handle and delete(data)
is called if the object is empty. Works only if Anim8_RemoveIfEmpty
is also activated.
func void Anim8_RemoveDataIfEmpty(var int handle, var int on)\n
Parameters var int handle
Handle returned from Anim8_New
var int on
TRUE
: enable, FALSE
: disable "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_1","title":"Anim8
","text":"Anim8
Packet core. Gives the object a new command to process.
func void Anim8(var int handle, var int target, var int span, var int interpol)\n
Parameters var int handle
Handle returned from Anim8_New
var int target
Target value of this command. When the object's value has reached this value, the command is considered completed and deleted. var int span
Action duration in milliseconds var int interpol
What form of movement is used (See constants for this) "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8q","title":"Anim8q
","text":"Anim8q
As already mentioned above, Anim8 can also process several commands one after the other. While Anim8 completely resets the object and deletes all commands, Anim8q just appends a new command to the list. This will be processed as soon as the previous one is completed.
func void Anim8q(var int handle, var int target, var int span, var int interpol)\n
Parameters var int handle
Handle returned from Anim8_New
var int target
Target value of this command. When the object's value has reached this value, the command is considered completed and another one in the queue will start. var int span
Action duration in milliseconds var int interpol
What form of movement is used (See constants for this) "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_callonremove","title":"Anim8_CallOnRemove
","text":"Anim8_CallOnRemove
Registers a function to be called when the object is deleted (e.g. by Anim8_RemoveIfEmpty
)
func void Anim8_CallOnRemove(var int handle, var func dfnc)\n
Parameters var int handle
Handle returned from Anim8_New
var func dfnc
This function is called when the object is deleted "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#count-up-to-a-number","title":"Count up to a number","text":"Count from 0 to 10 in 10 seconds. We use the Print_Ext
function from Interface to display the text.
func void Example1()\n{\n // First we create a handle to a text:\n var int MyText; MyText = Print_Ext(20, 20, \"0\", Font_Screen, COL_White, -1);\n\n // After that we create a new, extended Anim8 object.\n // It gets a handler and the handle to the text as data:\n var int MyAnim8; MyAnim8 = Anim8_NewExt(0, MyLoop1, MyText, FALSE); \n // Start value 1, MyLoop1 as handler, MyText as data and no float\n\n // Now the command to count to 10:\n Anim8(MyAnim8, 10, 10000, A8_Constant); // With MyAnim8 to 10 within 10000ms with constant motion.\n\n // So that the text and the Anim8 object are deleted after the process. \n // Now we have to do two more things:\n Anim8_RemoveIfEmpty(MyAnim8, TRUE);\n Anim8_RemoveDataIfEmpty(MyAnim8, TRUE);\n};\n\nfunc void MyLoop1(var int MyText, var int Number)\n{\n var zCViewText t; t = _^(myText);\n\n // Now the text is set to the value of the Anim8 object:\n t.text = IntToString(Number);\n\n // As I said, everything is deleted fully automatically\n};\n
A similar example can be found in the Interface examples."},{"location":"zengin/scripts/extenders/lego/applications/anim8/#moving-zcvob-in-loop","title":"Moving zCVob in loop","text":"Now we make a vob constantly move back and forth, but without a mover. FrameFunctions are used for the loop:
var zCVob MyVob;\nvar int MyVobAni;\n\nfunc void Example2()\n{\n // We use Ikarus to get a pointer to a known VOB:\n MyVob = MEM_PtrToInst(MEM_SearchVobByName(\"MYVOB\"));\n // There must be a vob with the appropriate name in the world for this.\n\n // Since the positions of a vob are floats, this time Anim8 must also use floats:\n MyVobAni = Anim8_New(MyVob.trafoObjToWorld[3], TRUE);\n // The X position of the vob serves as the starting value.\n // We will also move it along this axis.\n\n // Now start a loop that \"nudges\" the vob over and over again:\n FF_Apply(MyVobLoop);\n};\n\nfunc void MyVobLoop()\n{\n // We get the pointer to the VOB again\n MyVob = MEM_PtrToInst(MEM_SearchVobByName(\"MYVOB\"));\n\n // Whenever there are no more commands, we add new ones:\n if(Anim8_Empty(MyVobAni))\n {\n // First move by three meters:\n Anim8(MyVobAni, addf(MyVob.trafoObjToWorld[3], mkf(300)), 1000, A8_SlowEnd);\n // Then wait half a second:\n Anim8q(MyVobAni, 0, 500, A8_Wait);\n // And then back again:\n Anim8q(MyVobAni, MyVob.trafoObjToWorld[3], 1000, A8_SlowEnd);\n // And wait another half a second:\n Anim8q(MyVobAni, 0, 500, A8_Wait);\n // Note the 'q' in the follow-up commands.\n // While Anim8 completely resets the command list, i.e. starts again, Anim8q appends the command to the queue.\n // So you can tinker with a command sequence.\n };\n // Of course, we must set the \"animated\" value to the VOB itself\n MyVob.trafoObjToWorld[3] = Anim8_Get(MyVobAni);\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/","title":"Bars","text":""},{"location":"zengin/scripts/extenders/lego/applications/bars/#bars","title":"Bars","text":"Info
Dependencies: - PermMem - View Implementation: Bars.d on GitHub
This package makes it very easy to add new bars, for e.g. stamina.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#initialization","title":"Initialization","text":"Initialize with LeGo_Bars
flag.
LeGo_Init(LeGo_Bars);\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#functions","title":"Functions","text":"Note
If the GothicBar
prototype is selected as the initial type (GothicBar@
as the constructor), the user's own bars are visually indistinguishable from those used in Gothic.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_create","title":"Bar_Create
","text":"Bar_Create
Creates a new bar from a constructor instance.
func int Bar_Create(var int inst)\n
Parameters
var int inst
Constructor instance of Bar
class Return value
The function returns the address of the new bar, aka the handle.
Examples var int bar; bar = Bar_Create(GothicBar@);
var int bar; bar = Bar_Create(GothicBar@); // Create a new bar\nBar_SetPercent(bar, 50); // And set the value to 50%\n
func void Example_1()\n{\n var int bar; bar = Bar_Create(GothicBar@); // Create a new bar\n Bar_SetPercent(bar, 50); // And set the value to 50%\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_delete","title":"Bar_Delete
","text":"Bar_Delete
Deletes a bar from the screen and from memory.
func void Bar_Delete(var int bar)\n
Parameters
var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setmax","title":"Bar_SetMax
","text":"Bar_SetMax
Changes a bar's maximum value but does not update its bar length (only Bar_SetPercent
, Bar_SetPromille
and Bar_SetValue
)
func void Bar_SetMax(var int bar, var int max)\n
Parameters "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setvalue","title":"Bar_SetValue
","text":"Bar_SetValue
Sets the value of the bar.
func void Bar_SetValue(var int bar, var int val)\n
Parameters var int bar
Handle returned from Bar_Create
var int val
New value of the bar "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setpercent","title":"Bar_SetPercent
","text":"Bar_SetPercent
Sets the value of the bar but as a percentage (0..100).
func void Bar_SetPercent(var int bar, var int perc)\n
Parameters var int bar
Handle returned from Bar_Create
var int perc
New value of the bar in percent "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setpromille","title":"Bar_SetPromille
","text":"Bar_SetPromille
Sets the value of the bar but per mille (0..1000).
func void Bar_SetPromille(var int bar, var int pro)\n
Parameters var int bar
Handle returned from Bar_Create
var int pro
New value of the bar in per mille "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_hide","title":"Bar_Hide
","text":"Bar_Hide
Hides a bar. It will not be deleted.
func void Bar_Hide(var int bar)\n
Parameters var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_show","title":"Bar_Show
","text":"Bar_Show
Displays a bar again after using Bar_Hide
.
func void Bar_Show(var int bar)\n
Parameters var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_moveto","title":"Bar_MoveTo
","text":"Bar_MoveTo
Move the bar to virtual position.
func void Bar_MoveTo(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New horizontal position in virtual coordinates var int y
New vertical position in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_movetopxl","title":"Bar_MoveToPxl
","text":"Bar_MoveToPxl
Move the bar to pixel position.
func void Bar_MoveToPxl(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New horizontal position in pixels var int y
New vertical position in pixels "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setalpha","title":"Bar_SetAlpha
","text":"Bar_SetAlpha
Sets the transparency of the bar.
func void Bar_SetAlpha(var int bar, var int alpha)\n
Parameters var int bar
Handle returned from Bar_Create
var int alpha
Transparency value (0..255) "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setbartexture","title":"Bar_SetBarTexture
","text":"Bar_SetBarTexture
Sets the foreground texture of the bar.
func void Bar_SetBarTexture(var int bar, var string barTex)\n
Parameters var int bar
Handle returned from Bar_Create
var string barTex
The new foreground texture "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setbacktexture","title":"Bar_SetBackTexture
","text":"Bar_SetBackTexture
Sets the background texture of the bar.
func void Bar_SetBackTexture(var int bar, var string backTex)\n
Parameters var int bar
Handle returned from Bar_Create
var string backTex
The new background texture "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_resize","title":"Bar_Resize
","text":"Bar_Resize
Resize an existing bar.
func void Bar_Resize(var int bar, var int width, var int height)\n
Parameters var int bar
Handle returned from Bar_Create
var int width
New width in virtual coordinates var int height
New height in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_resizepxl","title":"Bar_ResizePxl
","text":"Bar_ResizePxl
Resize existing bar (in pixels).
func void Bar_ResizePxl(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New width in pixels var int y
New height in pixels "},{"location":"zengin/scripts/extenders/lego/applications/bars/#examples","title":"Examples","text":"Note
The bars assume a certain basic understanding of the PermMem module.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#a-dedicated-experience-bar","title":"A dedicated experience bar","text":"Bars implement the Bar
class. It looks like this:
class Bar\n{\n var int x; // X position on the screen (middle of the bar)\n var int y; // Y position on the screen (middle of the bar)\n var int barTop; // Top/bottom margin\n var int barLeft; // Left/right margin\n var int width; // Bar width\n var int height; // Bar height\n var string backTex; // Background texture\n var string barTex; // Actual bar texture\n var int value; // Current value\n var int valueMax; // Maximum value\n};\n
The GothicBar
prototype is a bar, which mimics the standard Gothic status bar. prototype GothicBar(Bar)\n{\n x = Print_Screen[PS_X] / 2;\n y = Print_Screen[PS_Y] - 20;\n barTop = 3;\n barLeft = 7;\n width = 180;\n height = 20;\n backTex = \"Bar_Back.tga\";\n barTex = \"Bar_Misc.tga\";\n value = 100;\n valueMax = 100;\n};\n
It is much easier to set up a new instance using this prototype. GothicBar
without modifications can be found as the GothicBar@
instance, which we used to create the bar in the example above. GothicBar
is located in the middle of the screen and looks exactly like the Gothic underwater bar.
// Instance created from \ninstance Bar_1(GothicBar)\n{\n x = 100;\n y = 20;\n};\n\nfunc void Example_1()\n{\n // Example_1 could e.g. be called in Init_Global\n FF_ApplyOnce(Loop_1);\n};\n\nfunc void Loop_1()\n{\n // Example_1 gets this loop running.\n // Here the bar should be constructed once\n // and then adapted to the EXP of the hero:\n var int MyBar;\n if(!Hlp_IsValidHandle(MyBar))\n {\n MyBar = Bar_Create(Bar_1); // Our Bar_1\n };\n // The rest is probably self-explanatory:\n Bar_SetMax(MyBar, hero.exp_next);\n Bar_SetValue(MyBar, hero.exp);\n};\n
Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/","title":"Bloodsplats","text":""},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplats","title":"Bloodsplats","text":"Info
Dependencies: - Floats - View - Random - Anim8 Implementation: Bloodsplats.d on GitHub
If this package is activated, red blood splatters will appear on the screen when the hero takes damage. For this, the damage perception for the hero is redirected to _B_HeroDamage()
. To use the Bloodsplats, the enclosed textures must be available. Also, the VFX \"HERO_HURT\" (also included) should be entered in the VfxInst.d
to create an even better hit effect. All textures used here are from CGTextures.com. If you use Bloodsplats in your modification, this site must be noted in the credits.
Tip
See user constants to edit behavior of this packet.
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#initialization","title":"Initialization","text":"Initialize with LeGo_Bloodsplats
flag.
LeGo_Init(LeGo_Bloodsplats);\n
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplat","title":"Bloodsplat
","text":"Bloodsplat
Puts a blood splatter on the screen.
func void Bloodsplat(var int damage)\n
Parameters var int damage
The damage (affects the size of the splatter) "},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplats_rage","title":"Bloodsplats_Rage
","text":"Bloodsplats_Rage
Pretty pointless feature that smears the entire screen.
func void Bloodsplats_Rage()\n
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#npc_getpercfunc","title":"Npc_GetPercFunc
","text":"Npc_GetPercFunc
oCNpc::GetPerceptionFunc
engine function wrapper
func int Npc_GetPercFunc(var C_Npc npc, var int type)\n
Parameters var C_NPC npc
NPC whose perception is checked var int type
Checked perception type (form Constant.d
) Return value
The function returns the state of NPCs selected perception.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/","title":"Buffs","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buffs","title":"Buffs","text":"Info
Dependencies: - PermMem - FrameFunctions Implementation: Buffs.d on GitHub
This package allows you to easily create status effects that can affect any NPC. Status effects on the hero are displayed graphically in a bar.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#initialization","title":"Initialization","text":"Initialize with LeGo_Buffs
flag.
LeGo_Init(LeGo_Buffs);\n
Warning
This package is still experimental and not included in the LeGo_All
initialization flag.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_apply","title":"Buff_Apply
","text":"Buff_Apply
Applies a status effect to an NPC.
func int Buff_Apply(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_applyunique","title":"Buff_ApplyUnique
","text":"Buff_ApplyUnique
Buff_Apply
, but nothing happens if a status effect of that kind is already on the NPC.
func int Buff_ApplyUnique(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated or 0
if the buff is already applied on the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_applyorrefresh","title":"Buff_ApplyOrRefresh
","text":"Buff_ApplyOrRefresh
Buff_Apply
, but if a status effect of this type is already affecting the NPC, the duration will be reset.
func int Buff_ApplyOrRefresh(var C_NPC n, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated or refreshed.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_refresh","title":"Buff_Refresh
","text":"Buff_Refresh
Resets the duration of the buff.
func void Buff_Refresh(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff to refresh "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_remove","title":"Buff_Remove
","text":"Buff_Remove
Removes the buff from the all NPCs.
func void Buff_Remove(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff to remove "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_removeall","title":"Buff_RemoveAll
","text":"Buff_RemoveAll
Removes the buffs form the NPC.
func void Buff_RemoveAll(var C_NPC npc, var int buffInstance)\n
Parameters var C_NPC npc
NPC whose buff should be removed "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_getnpc","title":"Buff_GetNpc
","text":"Buff_GetNpc
Returns a pointer to the NPC, which is affected by the buff.
func int Buff_GetNpc(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff Return value
The function returns a pointer to the NPC, which is affected by the buff.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_has","title":"Buff_Has
","text":"Buff_Has
Checks if the NPC already has an effect applied.
func int Buff_Has(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns TRUE
if the NPC has an effect applied. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#save_getfuncid","title":"SAVE_GetFuncID
","text":"SAVE_GetFuncID
Same as MEM_GetFuncID
but gets the current instance.
func int SAVE_GetFuncID(var func f)\n
Parameters var func f
Function whose ID is got
Return value
The function returns the ID of given function.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#lcbuff-class","title":"lCBuff class","text":"The buffs package implements an lCBuff
class, which looks like this:
class lCBuff\n{\n var string name; // buff name \n var int buffType; // GOOD / NEUTRAL / BAD | 1 / 0 / -1\n var int targetID; // NPC that is currently affected by this buff\n var int durationMS; // buff duration in milliseconds\n var int tickMS; // tick duration in milliseconds, first tick occurs at tickMS milliseconds\n var int nextTickNr; // e.g. before the first tick this will be 0; OBSOLETE, remove when possible\n\n var int OnApply; \n var int OnTick;\n var int OnRemoved;\n\n var string buffTex; // associated texture - currently only used for buffs applied on the hero\n // var int originID; // Who casted/created this buff?\n\n // Internal, no need to set during instance construction\n var int _startedTime;\n var int _endTime; // Not redundant with durationMS because buffs can be refreshed\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#delayed-poison","title":"Delayed poison","text":"instance deadly_poison(lCBuff)\n{\n name = \"Deadly poison\";\n bufftype = BUFF_BAD;\n\n durationMS = 10*1000; // 10 seconds long\n tickMS = 1000; // Every second\n\n buffTex = \"POISON.TGA\";\n};\n
Damage should also be added:
func void deadly_poison_damage(var int buffHandle)\n{\n var int ptr; ptr = Buff_GetNpc(buffHandle);\n if (!ptr) { return; }; // Can happen if e.g. the world was changed\n\n var C_NPC npc; npc = _^(ptr);\n Npc_ChangeAttribute(npc, ATR_HITPOINTS, -3); // 3 damage\n};\n
For complicated technical reasons we use the function SAVE_GetFuncID
instead of MEM_GetFuncID
. instance deadly_poison(lCBuff)\n{\n name = \"Deadly poison\";\n bufftype = BUFF_BAD;\n\n durationMS = 10 * 1000; //10 seconds long\n tickMS = 1000; // Every second\n\n onTick = SAVE_GetFuncID(deadly_poison_damage); // The damage should be applied every second\n buffTex = \"POISON.TGA\";\n};\n
For example, if this buff is now applied to the hero, by calling Buff_Apply(hero, deadly_poison)
, he loses a total of 30 HP over 10 seconds.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/","title":"Buttons","text":""},{"location":"zengin/scripts/extenders/lego/applications/buttons/#buttons","title":"Buttons","text":"Info
Dependencies: - PermMem - View Implementation: Buffs.d on GitHub
This package extends the handling of the mouse and allows creating rectangular buttons, which react to mouse (hover) entry and exit as well as a mouse click.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#initialization","title":"Initialization","text":"Initialize with LeGo_Buttons
flag.
LeGo_Init(LeGo_Buttons);\n
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_create","title":"Button_Create
","text":"Button_Create
Creates a button. It is initially hidden (not visible and does not react to the mouse). The three callback functions have the following signature void f(int handle)
.
func int Button_Create(var int posx, var int posy, var int width, var int height, var string tex, var func on_enter, var func on_leave, var func on_click)\n
Parameters var int posx
The horizontal position of the button in virtual coordinates var int posy
The vertical position of the button in virtual coordinates var int width
Width of the button in virtual coordinates var int height
Height of the button in virtual coordinates var string tex
Name of the button texture var func on_enter
This function is called when the mouse enters the button var func on_leave
This function is called when the mouse leaves the button var func on_click
This function is called when the user performs a mouse click on the button (left mouse button) Return value
The function returns a handle to created button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_createpxl","title":"Button_CreatePxl
","text":"Button_CreatePxl
Button_Create
with pixels instead of virtual coordinates.
func int Button_CreatePxl(var int posx, var int posy, var int width, var int height, var string tex, var func on_enter, var func on_leave, var func on_click)\n
Parameters var int posx
The horizontal position of the button in pixels var int posy
The vertical position of the button in pixels var int width
Width of the button in pixels var int height
Height of the button in pixels var string tex
Name of the button texture var func on_enter
This function is called when the mouse enters the button var func on_leave
This function is called when the mouse leaves the button var func on_click
This function is called when the user performs a mouse click on the button (left mouse button) Return value
The function returns a handle to created button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_delete","title":"Button_Delete
","text":"Button_Delete
Completely deletes a button.
func void Button_Delete(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_show","title":"Button_Show
","text":"Button_Show
Shows the button and makes it respond to the mouse.
func void Button_Show(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_hide","title":"Button_Hide
","text":"Button_Hide
Hides the button and disables it, so it is no longer responding to the mouse.
func void Button_Hide(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_settexture","title":"Button_SetTexture
","text":"Button_SetTexture
Sets the texture of the button.
func void Button_SetTexture(var int hndl, var string tex)\n
Parameters var int hndl
Handle returned from Button_Create
var string tex
Name of the new texture "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_setcaption","title":"Button_SetCaption
","text":"Button_SetCaption
Displays a centered text on the button.
func void Button_SetCaption(var int hndl, var string caption, var string font)\n
Parameters var int hndl
Handle returned from Button_Create
var string caption
The text to be displayed var string font
The font in which the text should be displayed "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_createmouseover","title":"Button_CreateMouseover
","text":"Button_CreateMouseover
Attaches a mouseover box to the cursor.
func void Button_CreateMouseover(var string text, var string font)\n
Parameters var string text
The text in the mouseover box var string font
The font of the text "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_deletemouseover","title":"Button_DeleteMouseover
","text":"Button_DeleteMouseover
Deletes the mouseover box.
func void Button_DeleteMouseover()\n
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_activate","title":"Button_Activate
","text":"Button_Activate
Activates the button, so it reacts to the mouse. Does not change the visibility.
func void Button_Activate(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_deactivate","title":"Button_Deactivate
","text":"Button_Deactivate
Disables the button, so it no longer reacts to the mouse.
func void Button_Deactivate(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_setuserdata","title":"Button_SetUserData
","text":"Button_SetUserData
Sets the user data of the button, an integer, to give the button individual information.
func void Button_SetUserData(var int hndl, var int data)\n
Parameters var int hndl
Handle returned from Button_Create
var int data
Individual integer of the button (part of the internal _Button
class) "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getuserdata","title":"Button_GetUserData
","text":"Button_GetUserData
Gets the user data of the button.
func int Button_GetUserData(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the user data of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getstate","title":"Button_GetState
","text":"Button_GetState
Gets the status of the button as a bit field. See User Constants.
func int Button_GetState(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the status of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_move","title":"Button_Move
","text":"Button_Move
Moves the button by the given value in pixels. posx = posx + nposx
func void Button_Move(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
X-axis shift in pixels var int nposy
Y-axis shift in pixels "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_movevrt","title":"Button_MoveVrt
","text":"Button_MoveVrt
Moves the button by the given value in virtual coordinates. posx = posx + nposx
func void Button_Move(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
X-axis shift in virtual coordinates var int nposy
Y-axis shift in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_moveto","title":"Button_MoveTo
","text":"Button_MoveTo
Moves a button to the given position in pixels. posx = nposx
func void Button_MoveVrt(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
New horizontal position in pixels var int nposy
New vertical position in pixels "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_movetovrt","title":"Button_MoveToVrt
","text":"Button_MoveToVrt
Moves a button to the given position in virtual coordinates. posx = nvposx
func void Button_MoveVrt(var int hndl, var int nvposx, var int nvposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nvposx
New horizontal position in virtual coordinates var int nvposy
New vertical position in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getviewhandle","title":"Button_GetViewHandle
","text":"Button_GetViewHandle
Returns the button's zCView
as a handle.
func int Button_GetViewHandle(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as a handle.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getviewptr","title":"Button_GetViewPtr
","text":"Button_GetViewPtr
Returns the button's zCView
as a pointer.
func int Button_GetViewPtr(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as a pointer.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getview","title":"Button_GetView
","text":"Button_GetView
Returns the button's zCView
as an object.
func zCView Button_GetView(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as an object.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getcaptionptr","title":"Button_GetCaptionPtr
","text":"Button_GetCaptionPtr
Returns the pointer to the text of the button.
func int Button_GetCaptionPtr(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the pointer to the text of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/","title":"Console Commands","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#console-commands","title":"Console Commands","text":"Info
Dependencies: - PermMem - HookEngine Implementation: ConsoleCommands.d on GitHub
This package allows you to create new console commands.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#initialization","title":"Initialization","text":"Initialize with LeGo_ConsoleCommands
flag.
LeGo_Init(LeGo_ConsoleCommands);\n
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_register","title":"CC_Register
","text":"CC_Register
Registers a new console command.
func void CC_Register(var func f, var string cmdPrefix, var string description)\n
Parameters var func f
This function is executed when the cmdPrefix
command is entered in the console. The function signature is func string f(var string p0)
. The string passed is everything that was specified in the console after the actual command. The return value is then displayed in the console. var string cmdPrefix
This is a command, which can be entered in the console. var string description
This text appears next to the command (in zSpy) when you use the help
command in the console. "},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_remove","title":"CC_Remove
","text":"CC_Remove
Removes a function from the console commands.
func void CC_Remove(var func f)\n
Parameters var func f
This function will be removed, i.e. the associated command will no longer work. "},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_active","title":"CC_Active
","text":"CC_Active
Checks whether the function passed is already part of a console command.
func int CC_Active(var func f)\n
Parameters var func f
Function being checked Return value
The function returns TRUE
if there is a corresponding function, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#basic-command-example","title":"Basic command example","text":"As a basic example - let us create a version command, which prints a version of our modification. Firstly, we declare a constant string
variable to hold the version string to be shown.
const string Mod_Version = \"My mod version 0.1alpha\";\n
Next we create the command function. Note
Notice the correct function signature. If you do not adhere to the correct function signature, the command will crash the game.
// This function is called by our console\nfunc string CC_ModVersion(var string param)\n{\n return Mod_Version;\n};\n
We then have to register the functions. For convenience, I created a new RegisterConsoleFunctions
function to initialize all console commands. The function is really simple. func void RegisterConsoleFunctions()\n{\n CC_Register (CC_ModVersion, \"version\", \"Version of my amazing mod.\");\n};\n
Lastly, we have to call this function from INIT_GLOBAL
function. func void INIT_GLOBAL()\n{\n // will be called for every world (from INIT_<LevelName>)\n Game_InitGerman();\n\n // Ikarus initialization\n MEM_InitAll();\n\n // LeGo initialization\n LeGo_Init(LeGo_ConsoleCommands);\n\n // Here we register all of our commands\n RegisterConsoleFunctions();\n\n // the rest of the code \n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/","title":"Cursor","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor","title":"Cursor","text":"Info
Dependencies: - Floats - FrameFunctions - View Implementation: Cursor.d on GitHub
This package implements Gothic in-game mouse cursor support. To visually display the cursor there is a Cursor.tga
file in the resources, but the texture can be changed in user constants.
Warning
The cursor only works if the mouse is activated in the Gothic settings. It can be done directly from the scripts. See the Ini file access.
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#initialization","title":"Initialization","text":"Initialize with LeGo_Cursor
flag.
LeGo_Init(LeGo_Cursor);\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#variables","title":"Variables","text":" var int Cursor_X
Always contains the X coordinate of the mouse cursor. var int Cursor_Y
Always contains the Y coordinate of the mouse cursor. var float Cursor_RelX
Always contains the relative X coordinate of the mouse cursor as an Ikarus float. var float Cursor_RelY
Always contains the relative Y coordinate of the mouse cursor as an Ikarus float. var int Cursor_Wheel
Variable containing the value of the mouse wheel. var int Cursor_Left
Variable that always contains the KeyState of the left mouse button. var int Cursor_Mid
Variable that always contains the KeyState of the middle mouse button. var int Cursor_Right
Variable that always contains the KeyState of the right mouse button. var int Cursor_Event
An event handler that can send information about the mouse cursor. It can be used with all functions of the EventHandler package. var int Cursor_NoEngine
Variable that can prevent the engine from working. If is set to TRUE
the engine no longer reacts to mouse movements. "},{"location":"zengin/scripts/extenders/lego/applications/cursor/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor_hide","title":"Cursor_Hide
","text":"Cursor_Hide
Hides the displayed mouse cursor.
func void Cursor_Hide()\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor_show","title":"Cursor_Show
","text":"Cursor_Show
Shows the mouse cursor.
func void Cursor_Show()\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#setmouseenabled","title":"SetMouseEnabled
","text":"SetMouseEnabled
Can manually enable or disable the mouse.
func void SetMouseEnabled(var int enabled)\n
Parameters var int enabled
TRUE
- Mouse activated "},{"location":"zengin/scripts/extenders/lego/applications/cursor/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#click-a-button","title":"Click a button","text":"We use a View to display a button to be clicked. The FrameFunctions take care of the loop to check whether a click was made.
var int Button;\nfunc void Example1()\n{\n // We show the cursor and at the same time a button to be clicked:\n Cursor_Show();\n\n // New View:\n Button = View_CreatePxl(5, 5, 125, 50);\n View_SetTexture(Button, \"BUTTONTEX.TGA\");\n View_Open(Button);\n\n // Optionally, mouse can be switched off for the engine:\n Cursor_NoEngine = true; // -> The engine then no longer reacts to movements, so the camera does not move either\n\n // Enable loop function:\n FF_ApplyOnce(Button_Click);\n};\n\nfunc void Button_Click()\n{\n if(Cursor_Left != KEY_PRESSED) { return; }; // Exit the function if the left mouse button was not pressed\n\n if(Cursor_X >= 5 && Cursor_X <= 125\n && Cursor_Y >= 5 && Cursor_Y <= 50) // Simply take over the coordinates of the view\n { \n // Here the button was clicked.\n // Remove button and end loop:\n View_Close(Button);\n View_Delete(Button);\n Button = 0;\n\n // Allow the engine to continue working:\n Cursor_NoEngine = false;\n\n FF_Remove(Button_Click);\n\n // Hide the mouse:\n Cursor_Hide();\n };\n};\n
This also can be done by the Buttons package instead of View.
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#event-handler","title":"Event handler","text":"Since LeGo 2.2 there is also an event handler (var int Cursor_Event
) in the cursor package. This example briefly explains how it works:
func void Example2()\n{\n // We register MyCursorListener as the handler/listener of the Cursor_Event:\n Event_Add(Cursor_Event, MyCursorListener);\n\n // From now on, MyCursorListener will be called whenever the cursor has something to report.\n};\n\nfunc void MyCursorListener(var int state)\n{\n // The rest is self-explanatory:\n\n if(state == CUR_WheelUp)\n {\n PrintS(\"Wheel up!\");\n };\n if(state == CUR_WheelDown)\n {\n PrintS(\"Wheel down!\");\n };\n if(state == CUR_LeftClick)\n {\n PrintS(\"Leftclick!\");\n };\n if(state == CUR_RightClick)\n {\n PrintS(\"Rightclick!\");\n };\n if(state == CUR_MidClick)\n {\n PrintS(\"Wheelclick!\");\n };\n};\n
Constants used in the example can be found in the user constants."},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/","title":"Dialoggestures","text":""},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#dialoggestures","title":"Dialoggestures","text":"Info
Dependencies: - AI_Function Implementation: Dialoggestures.d on GitHub
This package can modify the NPCs' gestures during dialogue to better bring out emotions.
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag","title":"DIAG
","text":"DIAG
With this function the dialog gestures for all NPCs can be overridden. To understand the principle, it is recommended to take a look at the examples.
The full name of the animation can be described as follows:
DIAG_Prefix + aniName + DIAG_Suffix + ((rand() % (max - (min - 1))) + min).ToString(\"00\");\n
DIAG_Prefix
and DIAG_Suffix
are user constants.
func void DIAG(var string AniName, var int Min, var int Max)\n
Parameters var string AniName
The new dialogue gesture var int Min
Lowest animation number var int Max
Highest animation number "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_reset","title":"DIAG_Reset
","text":"DIAG_Reset
Resets the dialog gestures to the default.
func void DIAG_Reset()\n
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_setani","title":"DIAG_SetAni
","text":"DIAG_SetAni
Sets animation directly.
func void DIAG_SetAni(var string AniName)\n
Parameters var string AniName
Animation name "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_setminmax","title":"DIAG_SetMinMax
","text":"DIAG_SetMinMax
Sets animation numbers directly.
func void DIAG_SetMinMax(var int min, var int max)\n
Parameters var int min
Lowest animation number var int max
Highest animation number "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#examples","title":"Examples","text":"Note
See Examples in the Trialoge article.
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/","title":"Focusnames","text":""},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames","title":"Focusnames","text":"Info
Dependencies: - Interface - HookEngine Implementation: Focusnames.d on GitHub
This package colors the focus names of the NPCs in appropriate colors according to the behavior defined below (alpha values are taken into account). Also affects monsters. (Mobs/Items get Color_Neutral)
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#initialization","title":"Initialization","text":"Initialize with LeGo_Focusnames
flag.
LeGo_Init(LeGo_Focusnames);\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#usage","title":"Usage","text":"If you want to change colors for any behavior edit the following functions directly in Focusnames.d
file.
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_friendly","title":"Focusnames_Color_Friendly
","text":"Focusnames_Color_Friendly
func int Focusnames_Color_Friendly()\n{\n return RGBA(0, 255, 0, 255); // Green\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_neutral","title":"Focusnames_Color_Neutral
","text":"Focusnames_Color_Neutral
func int Focusnames_Color_Neutral()\n{\n return RGBA(255, 255, 255, 255); // White\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_angry","title":"Focusnames_Color_Angry
","text":"Focusnames_Color_Angry
func int Focusnames_Color_Angry()\n{\n return RGBA(255, 180, 0, 255); // Orange\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_hostile","title":"Focusnames_Color_Hostile
","text":"Focusnames_Color_Hostile
func int Focusnames_Color_Hostile()\n{\n return RGBA(255, 0, 0, 255); // Red\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/","title":"Gamestate","text":""},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate","title":"Gamestate","text":"Info
Dependencies: - EventHandler - Saves Implementation: Gamestate.d on GitHub
Gamestate package allows to check for different game states (game start, game load or level change).
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#initialization","title":"Initialization","text":"Initialize with LeGo_Gamestate
flag.
LeGo_Init(LeGo_Gamestate);\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate_addlistener","title":"Gamestate_AddListener
","text":"Gamestate_AddListener
Adds a listener/handler to the game-state event.
func void Gamestate_AddListener(var func listener)\n
Parameters var func listener
This function will be called on a game-state change. The current game-state is passed as a parameter. "},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate_removelistener","title":"Gamestate_RemoveListener
","text":"Gamestate_RemoveListener
Removes game-state listener.
func void Gamestate_RemoveListener(var func listener)\n
Parameters var func listener
Listener function to be removed. "},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#examples","title":"Examples","text":"There are now two possibilities. Everything can be done directly into the Init_Global
, or with EventHandler.
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#init_global","title":"Init_Global","text":"func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n if(Gamestate == Gamestate_NewGame) \n {\n MEM_Info(\"New game started.\");\n }\n else if(Gamestate == Gamestate_Loaded)\n {\n MEM_Info(\"Game loaded.\");\n }\n else if(Gamestate == Gamestate_WorldChange)\n {\n MEM_Info(\"Worldshift.\");\n }\n else\n {\n MEM_Info(\"I don't pass.\");\n };\n};\n
It can also be done like that:
func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n if(Gamestate == Gamestate_NewGame)\n {\n FF_Apply(MyLoop);\n FF_Apply(My2ndLoop);\n };\n};\n
This would have the same effect as: func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n FF_ApplyOnce(MyLoop);\n FF_ApplyOnce(My2ndLoop);\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#eventhandler","title":"EventHandler","text":"func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n Gamestate_AddListener(MyGamestateListener);\n};\n\nfunc void MyGamestateListener(var int state)\n{\n if(state == Gamestate_NewGame)\n {\n MEM_Info(\"New game started.\");\n }\n else if(state == Gamestate_Loaded)\n {\n MEM_Info(\"Game loaded.\");\n }\n else if(state == Gamestate_WorldChange)\n {\n MEM_Info(\"Worldshift.\");\n }\n else\n {\n MEM_Info(\"I don't pass.\");\n };\n};\n
This is the same as the Init_Global
example, but it may look more elegant to some. Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/applications/names/","title":"Names","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#names","title":"Names","text":"Info
Dependencies: - Talents Implementation: Names.d on GitHub
Allows the user to change NPC name e.g. after he shows up.
"},{"location":"zengin/scripts/extenders/lego/applications/names/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/applications/names/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#setname","title":"SetName
","text":"SetName
Should be set in InitGlobal().
func void SetName(var C_NPC npc, var string name)\n
Parameters var C_NPC npc
The NPC to be named var string name
The name of the NPC "},{"location":"zengin/scripts/extenders/lego/applications/names/#showname","title":"ShowName
","text":"ShowName
Permanently displays the name set by SetName
function above the npc.
func void ShowName(var C_NPC npc)\n
Parameters var C_NPC npc
The NPC whose name should be shown "},{"location":"zengin/scripts/extenders/lego/applications/names/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#show-the-name-of-an-npc-later","title":"Show the name of an NPC later","text":"instance PAL_100_Friend(C_NPC)\n{\n name = \"Paladin\";\n\n // [...]\n};\n\nfunc void Init_Global()\n{\n SetName(PAL_100_Friend, \"Arto\");\n};\n
At the start of the game, the name \"Paladin\" is displayed above PAL_100_Friend
. If ShowName(PAL_100_Friend);
is used during a dialogue, the name \"Arto\" is permanently visible above the npc.
"},{"location":"zengin/scripts/extenders/lego/applications/render/","title":"Render","text":""},{"location":"zengin/scripts/extenders/lego/applications/render/#render","title":"Render","text":"Info
Dependencies: - List - View - PermMem Implementation: Render.d on GitHub
With this package items can be rendered on the screen. Since items are rendered independently of the normal views, textures that are 'below' the items must also be managed by this package, this behaviour is managed by the priority system. The view with the highest priority is always rendered first, so it is at the bottom. In theory, any .3DS model can be rendered if you just create a suitable item script.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#initialization","title":"Initialization","text":"Initialize with LeGo_Render
flag.
LeGo_Init(LeGo_Render);\n
Warning
This package is still experimental and not included in LeGo_All
initialization flag.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/render/#render_additemprio","title":"Render_AddItemPrio
","text":"Render_AddItemPrio
Generates the render of an item, with a manually specified priority.
func int Render_AddItemPrio(var int itemInst, var int x1, var int y1, var int x2, var int y2, var int priority)\n
Parameters var int itemInst
The instance of the item to render var int x1
var int y1
The top left coordinate of the view var int x2
var int y2
The bottom right coordinate of the view var int priority
The priority of this render object Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_additem","title":"Render_AddItem
","text":"Render_AddItem
Generates the render of an item, with priority set to 0
.
func int Render_AddItem(var int itemInst, var int x1, var int y1, var int x2, var int y2)\n
Parameters var int itemInst
The instance of the item to render var int x1
var int y1
The top left coordinate of the view var int x2
var int y2
The bottom right coordinate of the view Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_addviewprio","title":"Render_AddViewPrio
","text":"Render_AddViewPrio
Generates the render of a View, with a manually specified priority.
func int Render_AddViewPrio(var int view, var int priority)\n
Parameters var int view
A handle to a View var int priority
The priority of this render object Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_addview","title":"Render_AddView
","text":"Render_AddView
Generates the render of a View, with priority set to 0
.
func int Render_AddView(var int view)\n
Parameters var int view
A handle to a View Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_openview","title":"Render_OpenView
","text":"Render_OpenView
Opens a render object. Only open render objects are displayed.
func void Render_OpenView(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/render/#render_closeview","title":"Render_CloseView
","text":"Render_CloseView
Closes a render object. Only open render objects are displayed.
func void Render_CloseView(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/render/#render_remove","title":"Render_Remove
","text":"Render_Remove
Deletes a render object. The associated view is deleted automatically.
func void Render_Remove(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/saves/","title":"Saves","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#saves","title":"Saves","text":"Info
Dependencies: - BinaryMachines Implementation: Saves.d on GitHub
Offers an open file stream that can read/write variables on save/load. It is used by PermMem, so you don't need to address it manually anymore.
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#initialization","title":"Initialization","text":"Initialize with LeGo_Saves
flag.
LeGo_Init(LeGo_Saves);\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#bw_savegame","title":"BW_Savegame
","text":"BW_Savegame
Custom function. It creates a stream to its own memory file, this can be filled with the BW_*
functions from the BinaryMachines.
func void BW_Savegame()\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#br_savegame","title":"BR_Savegame
","text":"BR_Savegame
Custom function. It opens a stream to a previously saved memory file, which can be read from the BinaryMachines using the BR_*
functions.
func void BR_Savegame()\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#save-a-high-score-list","title":"Save a high score list","text":"var string MyScoreList[10];\n
Since strings are not saved by the game by default, we use the functions from Saves.d
to create an additional memory file that only belongs to us. At the top the Saves.d file has two functions: BW_Savegame
and BR_Savegame
. BinaryMachines functions are used to save or read the file, we don't need to do anything else than to use them here, the rest is done by Saves.d
completely by itself. Therefore, we only modify these two functions.
func void BW_Savegame() \n{\n // Save high score list\n BW_String(MyScoreList[0]);\n BW_String(MyScoreList[1]);\n BW_String(MyScoreList[2]);\n BW_String(MyScoreList[3]);\n BW_String(MyScoreList[4]);\n BW_String(MyScoreList[5]);\n BW_String(MyScoreList[6]);\n BW_String(MyScoreList[7]);\n BW_String(MyScoreList[8]);\n BW_String(MyScoreList[9]);\n};\n\nfunc void BR_Savegame() \n{\n // Load high score list\n MyScoreList[0] = BR_String();\n MyScoreList[1] = BR_String();\n MyScoreList[2] = BR_String();\n MyScoreList[3] = BR_String();\n MyScoreList[4] = BR_String();\n MyScoreList[5] = BR_String();\n MyScoreList[6] = BR_String();\n MyScoreList[7] = BR_String();\n MyScoreList[8] = BR_String();\n MyScoreList[9] = BR_String();\n};\n
Tip
Since LeGo 2.0, such things can be implemented much more elegantly with PermMem.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/","title":"Trialoge","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#trialoge","title":"Trialoge","text":"Info
Dependencies: - AI_Function Implementation: Trialoge.d on GitHub
This package allows you to create conversations with any number of NPCs and control the camera during the dialog.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#initialization","title":"Initialization","text":"Initialize with LeGo_Trialoge
flag.
LeGo_Init(LeGo_Trialoge);\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#equipweapon","title":"EquipWeapon
","text":"EquipWeapon
Sektenspinner's function. Makes NPC equip a weapon.
func void EquipWeapon(var C_NPC slf, var int ItemInstance)\n
Parameters var C_NPC slf
NPC to have a weapon equipped var int ItemInstance
Weapon instance ID to be equipped Configuration
const int EquipWeapon_TogglesEquip = 1
Above constant configures the behaviour of the function when trying to equip an already equipped weapon:
0
- EquipWeapon
will do nothing 1
- EquipWeapon
will unequip this weapon "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getarmor","title":"Npc_GetArmor
","text":"Npc_GetArmor
Returns NPC's equipped armor.
func int Npc_GetArmor(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get the armor from Return value
The function returns instance of armor worn by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getmeleeweapon","title":"Npc_GetMeleeWeapon
","text":"Npc_GetMeleeWeapon
Returns NPC's equipped melee weapon.
func int Npc_GetMeleeWeapon(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get the weapon from Return value
The function returns instance ID of melee weapon equipped by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getrangedweapon","title":"Npc_GetRangedWeapon
","text":"Npc_GetRangedWeapon
Returns NPC's equipped ranged weapon.
func int Npc_GetRangedWeapon(var c_npc slf)\n
Parameters var C_NPC slf
NPC to get the weapon from Return value
The function returns instance ID of ranged weapon equipped by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_tradeitem","title":"Npc_TradeItem
","text":"Npc_TradeItem
Swaps NPCs equipped weapon.
func void Npc_TradeItem(var c_npc slf, var int itm0, var int itm1) \n
Parameters var C_NPC slf
NPC to perform operation on var int itm0
instance ID of item to remove var int itm1
instance ID of item to create and equip "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_update","title":"DiaCAM_Update
","text":"DiaCAM_Update
Sektenspinner's function that updates the dialogue camera. (Used internally.)
func void DiaCAM_Update()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_disable","title":"DiaCAM_Disable
","text":"DiaCAM_Disable
Completely disable the dialogue cameras.
func void DiaCAM_Disable()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_enable","title":"DiaCAM_Enable
","text":"DiaCAM_Enable
Resets the dialogue cameras to the default settings.
func void DiaCAM_Enable()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_wait","title":"TRIA_Wait
","text":"TRIA_Wait
Makes self
and other
wait for each other, e.g. for AI_GotoWP
actions for synchronization.
func void TRIA_Wait()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_invite","title":"TRIA_Invite
","text":"TRIA_Invite
Invites an NPC into a conversation. Must be called before TRIA_Start
.
func void TRIA_Invite(var C_NPC slf)\n
Parameters var C_NPC slf
The invited NPC "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_start","title":"TRIA_Start
","text":"TRIA_Start
Starts trialogues. Before that, all NPCs should be invited by TRIA_Invite
.
func void TRIA_Start()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_barrier","title":"TRIA_Barrier
","text":"TRIA_Barrier
Similar to TRIA_Wait
but applies to all participating NPCs.
func void TRIA_Barrier()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_next","title":"TRIA_Next
","text":"TRIA_Next
Sets the called npc to self
.
func void TRIA_Next(var C_NPC n0)\n
Parameters var C_NPC n0
NPC to set to self
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_cam","title":"TRIA_Cam
","text":"TRIA_Cam
Starts a tracking shot.
func void TRIA_Cam(var string evt)\n
Parameters var string evt
The name of the tracking shot in Spacer. If \"\"
is passed, the running trace shot will be aborted. "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_finish","title":"TRIA_Finish
","text":"TRIA_Finish
Ends an ongoing trialogue. Must always be called at the end, otherwise no further trialogues can be started.
func void TRIA_Finish()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#a-simple-trialogue","title":"A Simple Trialogue","text":"The following conversation is resolved via the trialogues:
Arto: I'm sorry Hero, but you can't pass here. Hero: Why not? Horka: The city has been closed. Hero: I have some gold with me, can we trade? Squelto: No. We are not open to bribery. Hero: Sure? Arto: I have to ask you to leave now. Hero: Well... instance TRIA_Test (C_INFO)\n{\n npc = PAL_100_Friend;\n nr = 10;\n condition = TRIA_Test_condition;\n information = TRIA_Test_info;\n important = FALSE;\n permanent = 1;\n description = \"TRIALOGTEST\";\n};\n\nfunc int TRIA_Test_condition()\n{\n return TRUE;\n};\n\nfunc void TRIA_Test_info()\n{\n var C_NPC Arto; Arto = Hlp_GetNpc(PAL_100_Friend); // He is the owner of dialogue\n var C_NPC Horka; Horka = Hlp_GetNpc(PAL_101_Horka);\n var C_NPC Squelto; Squelto = Hlp_GetNpc(PAL_102_Squelto);\n\n TRIA_Invite(Horka); // Invite Horka into this dialogue\n TRIA_Invite(Squelto); // Invite Squelto into this dialog\n TRIA_Start(); // Start the conversation\n // The hero and Arto do not have to/may not be invited. They are in dialogue anyway.\n\n // Hero now talks to Arto (self = Arto, other = Hero)\n TRIA_Next(Arto);\n\n DIAG_Reset();\n\n AI_Output (self, other, \"TRIA_TEST_00\"); //Sorry hero, but you can't pass here.\n\n // Hero now talks to Horka (self = Horka, other = Hero)\n TRIA_Next(Horka);\n\n AI_Output (other, self, \"TRIA_TEST_01\"); //Why not?\n\n AI_GotoNpc(self, other);\n AI_TurnToNpc(other, self);\n\n AI_Output (self, other, \"TRIA_TEST_02\"); //The city has been closed.\n\n // Hero looks around conspiratorially during the next sentence\n DIAG(\"Nervous\", 1, 2);\n\n AI_Output (other, self, \"TRIA_TEST_03\"); //I have some gold with me, can we trade?\n\n // Hero should now move normally again\n DIAG_Reset();\n\n // Start tracking shot\n TRIA_Cam(\"CAMERASTART\");\n\n // Hero now talks to Squelto (self = Squelto, other = Hero)\n TRIA_Next(Squelto);\n\n AI_TurnToNpc(other, self);\n\n DIAG(\"No\", 0, 1);\n AI_Output (self, other, \"TRIA_TEST_04\"); //No. We are not open to bribery.\n\n // Hero talks to Arto again (self = Arto, other = Hero)\n TRIA_Next(Arto);\n\n // Hero should now articulate questioningly\n DIAG(\"NotSure\", 0, 1);\n\n AI_Output (other, self, \"TRIA_TEST_05\"); //Sure?\n\n AI_TurnToNpc(other, self);\n\n // tracking shot end\n TRIA_Cam(\"\");\n\n // Arto should react angrily\n DIAG(\"Angry\", 0, 4);\n\n AI_Output (self, other, \"TRIA_TEST_06\"); //I have to ask you to leave now\n\n // Hero should now move normally again\n DIAG_Reset();\n\n AI_Output (other, self, \"TRIA_TEST_07\"); //Well...\n\n TRIA_Finish(); // End\n};\n
Note
In addition, here are still Dialoggestures used.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/","title":"AI_Function","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#ai_function","title":"AI_Function","text":"Info
Dependencies: - HookEngine Implementation: AI_Function.d on GitHub
This package allows time-delayed functions to be called by enqueuing the functions in the AI queue of the NPC in question. This can be very useful in writing cutscenes on engine or implementing new routines.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#initialization","title":"Initialization","text":"Initialize with LeGo_AI_Function
flag.
LeGo_Init(LeGo_AI_Function);\n
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#ai_function_1","title":"AI_Function
","text":"AI_Function
The script function function
is called with a delay: it joins the AI queue of slf
.
func void AI_Function(var C_NPC slf, var func function)\n
Parameters var C_NPC slf
NPC in whose AI queue the function is queued var func function
Name of function to be queued Additionally, there are some overloads of AI_Function
, which allow to call functions with parameters.
func void AI_Function_I (var C_NPC slf, var func function, var int param) {}; // Int\nfunc void AI_Function_N (var C_NPC slf, var func function, var int param) {}; // Instance (e.g. NPC)\nfunc void AI_Function_S (var C_NPC slf, var func function, var string param) {}; // String\nfunc void AI_Function_II (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Int\nfunc void AI_Function_NN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Instance\nfunc void AI_Function_SS (var C_NPC slf, var func function, var string param1, var string param2) {}; // String, String\nfunc void AI_Function_IS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Int, String\nfunc void AI_Function_SI (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Int\nfunc void AI_Function_NS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Instance, String\nfunc void AI_Function_SN (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Instance\nfunc void AI_Function_IN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Instance\nfunc void AI_Function_NI (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Int\n
Functions with more than two parameters cannot be called, but parameters can be passed indirectly via global variables. In the called function, self
can be accessed as follows:
var oCNpc slf; slf = _^(ECX);\n
Info
From LeGo 2.7.2 the global instance self
is provided correctly and can be used directly.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#enqueueing-a-simple-function","title":"Enqueueing a simple function","text":"Before a function is called, any Npc should first complete its AI queue.
Here the hero is supposed to run to a waypoint, and only when he has arrived is to start a tracking shot.
func void Example1() {\n Npc_ClearAIQueue(hero);\n AI_GotoWP(hero, \"MYWAYPOINT\");\n\n AI_Function_S(hero, Wld_SendTrigger, \"CAMERASTART\");\n};\n
As soon as the hero has reached the waypoint, Wld_SendTrigger(\"CAMERASTART\");
is called."},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/","title":"BinaryMachines","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binarymachines","title":"BinaryMachines","text":"Info
Dependencies: - None Implementation: BinaryMachines.d on GitHub
This package allows you to create and write your own files anywhere in the file system.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binarywriter","title":"BinaryWriter","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_newfile","title":"BW_NewFile
","text":"BW_NewFile
Creates the file with the file
name and opens a stream. Doesn't work if a stream is already open.
func int BW_NewFile(var string file)\n
Parameters var string file
Name of created file Return value
The function returns TRUE
if the file is successfully created and initialized, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_close","title":"BW_Close
","text":"BW_Close
Closes the current write stream.
func void BW_Close()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw","title":"BW
","text":"BW
Writes length
bytes from the data
to the stream, maximum 4 bytes.
func void BW(var int data, var int length)\n
Parameters var int data
Value of bytes var int length
Number of bytes "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_int","title":"BW_Int
","text":"BW_Int
Writes 4 bytes from the data
to the stream. Same as BW(data, 4)
.
func void BW_Int(var int data)\n
Parameters var int data
Integer value to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_char","title":"BW_Char
","text":"BW_Char
Writes the first character from the data
to the stream. Same as BW(Str_GetCharAt(data, 0), 1)
.
func void BW_Char(var string data)\n
Parameters var string data
Char to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_string","title":"BW_String
","text":"BW_String
Writes the data
terminated with \\0
to the stream.
func void BW_String(var string data)\n
Parameters var string data
String to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_byte","title":"BW_Byte
","text":"BW_Byte
Writes a byte from the data
to the stream. Same as BW(data, 1)
.
func void BW_Byte(var int data)\n
Parameters var int data
Byte value to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_bytes","title":"BW_Bytes
","text":"BW_Bytes
Writes length
of bytes from the pointer dataPtr
to the stream.
func void BW_Bytes(var int dataPtr, var int length)\n
Parameters var int dataPtr
Pointer of data to write var int length
Number of bytes "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_text","title":"BW_Text
","text":"BW_Text
Writes the string to the stream without terminating it. So it can no longer be read.
func void BW_Text(var string data)\n
Parameters var string data
Text to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_nextline","title":"BW_NextLine
","text":"BW_NextLine
Writes a paragraph to the stream.
func void BW_NextLine()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binaryreader","title":"BinaryReader","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_openfile","title":"BR_OpenFile
","text":"BR_OpenFile
Opens the file with the file
name and opens a stream. Doesn't work if a stream is already open.
func int BR_OpenFile(var string file)\n
Parameters var string file
File to be opened Return value
The function returns TRUE
if the file is successfully opened and initialized, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_close","title":"BR_Close
","text":"BR_Close
Closes the current read stream.
func void BR_Close()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br","title":"BR
","text":"BR
Reads bytes from the stream.
func int BR(var int length)\n
Parameters var int length
Number of bytes to read (maximum 4) Return value
The function returns the value of read bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_int","title":"BR_Int
","text":"BR_Int
Reads 4 bytes from the stream. Same as BR(4)
.
func int BR_Int()\n
Return value The function returns the read integer.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_char","title":"BR_Char
","text":"BR_Char
Reads a character from the stream. Same as BR(1)
.
func string BR_Char()\n
Return value The function returns the read character as a string
.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_string","title":"BR_String
","text":"BR_String
Reads a string terminated by \\0
from the stream.
func string BR_String()\n
Return value The function returns the read string.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_byte","title":"BR_Byte
","text":"BR_Byte
Reads a byte from the stream.
func int BR_Byte()\n
Return value The function returns the read byte.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_bytes","title":"BR_Bytes
","text":"BR_Bytes
Reads bytes from the stream.
func int BR_Bytes(var int length)\n
Parameters var int length
Number of bytes to read Return value
The function returns a pointer to the read bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_textline","title":"BR_TextLine
","text":"BR_TextLine
Reads a line from the stream.
func string BR_TextLine()\n
Return value The function returns the read line.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_text","title":"BR_Text
","text":"BR_Text
Reads a string of the given length from a stream.
func string BR_Text(var int length)\n
Parameters var int length
Number of characters to read Return value
The function returns the read string.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_nextline","title":"BR_NextLine
","text":"BR_NextLine
Changes the read position to the next paragraph, created with BW_NextLine
func void BR_NextLine()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#enginecalls","title":"Enginecalls","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_getlasterror","title":"WIN_GetLastError
","text":"WIN_GetLastError
Call of a Win32 API GetLastError
function
func int WIN_GetLastError()\n
Return value The function returns calling thread's last-error code.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_createfile","title":"WIN_CreateFile
","text":"WIN_CreateFile
Call of a Win32 API CreateFileA
function
func int WIN_CreateFile(var string lpFileName,var int dwDesiredAccess,var int dwShareMode,var int lpSecurityAttributes,var int dwCreationDisposition,var int dwFlagsAndAttributes,var int hTemplateFile)\n
Parameters Full description of parameters can be found here
Return value
Information about return value can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_writefile","title":"WIN_WriteFile
","text":"WIN_WriteFile
Call of a Win32 API WriteFile
function
func void WIN_WriteFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToWrite,var int lpNumberOfBytesWritten,var int lpOverlapped)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_readfile","title":"WIN_ReadFile
","text":"WIN_ReadFile
Call of a Win32 API ReadFile
function
func void WIN_ReadFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToRead,var int lpNumberOfBytesRead,var int lpOverlapped)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_closehandle","title":"WIN_CloseHandle
","text":"WIN_CloseHandle
Call of a Win32 API CloseHandle
function
func void WIN_CloseHandle(var int hObject)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_getfilesize","title":"WIN_GetFileSize
","text":"WIN_GetFileSize
Call of a Win32 API GetFileSize
function
func int WIN_GetFileSize(var int hFile,var int lpFileSizeHigh)\n
Parameters Full description of parameters can be found here
Return value
Information about return value can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#constants","title":"Constants","text":"In addition there are some constants defined for use with the specific engine calls.
const int CREATE_ALWAYS = 2;\nconst int OPEN_EXISTING = 3;\nconst int GENERIC_ALL = 1073741824;\nconst int GENERIC_READ = -2147483648;\nconst int FILE_SHARE_READ = 1;\nconst int FILE_SHARE_WRITE = 2;\nconst int FILE_SHARE_DELETE = 4;\nconst int FILE_ATTRIBUTE_NORMAL = 128;\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#save-and-load-variables","title":"Save and load variables","text":"const string filename = \"System\\MySave.sav\";\n\nvar string s0; // string\nvar int i1; // int\nvar int b2; // byte\nvar string c3; // char\n\nfunc void SaveMyData() \n{\n if(BW_NewFile(filename)) // Create a new file:\n { \n BW_String(s0);\n BW_Int(i1);\n BW_Byte(b2);\n BW_Char(c3); // Save stuff..\n BW_Close(); // ..and close.\n };\n};\n\nfunc void LoadMyData() {\n if(BR_OpenFile(filename)) // Try to open file:\n { \n s0 = BR_String();\n i1 = BR_Int();\n b2 = BR_Byte();\n c3 = BR_Char(); // Read in values..\n BR_Close(); // ..and close.\n }\n else \n {\n SaveMyData(); // Otherwise create a save file.\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#congratulate-the-player","title":"Congratulate the player","text":"func void Certificate(var string Username, var int Score) \n{\n var string filename; filename = ConcatStrings(Username, \"'s Certificate.txt\");\n BW_NewFile(filename); // Username + \"s Certificate.txt\". The file is then in the Gothic directory.\n BW_Text(\"Congratulations \"); BW_Text(Username);\n BW_TextLine(\"!\");\n\n BW_Text(\"You have reached \");\n BW_Text(IntToString(Score)); // Not BW_Int!\n BW_TextLine(\" Points in this fun game.\");\n\n BW_NextLine();\n\n BW_Text(\"Best regards, Author\");\n BW_Close();\n\n /*\n When calling: Certificate(\"Player\", 1000);\n a file with the name 'Player's Certificate.txt' would come out which would contain the following:\n\n Congratulations Player\n You have reached 1000 Points in this fun game.\n\n Best regards, Author\n */\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#the-location-of-an-npcs","title":"The location of an NPCs","text":"func void BW_NpcPosition(var C_NPC slf) \n{\n var int ptr; ptr = MEM_Alloc(60); // 16 * 4\n MEM_CopyBytes(MEM_InstToPtr(slf) + 60, ptr, 60); // Copy slf.trafoObjToWorld\n BW_Bytes(ptr, 60); // Writes the 60 copied bytes\n MEM_Free(ptr); // And clean up..\n};\n\nfunc void BR_NpcPosition(var C_NPC slf) \n{\n var int ptr; ptr = BR_Bytes(60); // Read 60 bytes\n MEM_CopyBytes(ptr, MEM_InstToPtr(slf) + 60, 60); // Paste back into slf\n MEM_Free(ptr); // And clean up again..\n};\n\n/*\n Normal use:\n BW_NewFile(file);\n BW_NpcPosition(hero);\n BW_Close();\n*/\n
Note
Examples originally written by Gottfried and posted on World of Gothic forum.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/","title":"Draw3D","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#draw3d","title":"Draw3D","text":"Info
Dependencies: - PermMem - HookEngine Implementation: Draw3D.d on GitHub
This package allows you to draw various shapes (such as lines or bounding boxes) in three-dimensional space. This makes debugging visualizations of coordinates in the world possible.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#initialization","title":"Initialization","text":"Initialize with LeGo_Draw3D
flag.
LeGo_Init(LeGo_Draw3D);\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#line","title":"Line","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawline","title":"DrawLine
","text":"DrawLine
Creates and draws a new line and returns its handle.
func int DrawLine(var int startPosPtr, var int endPosPtr, var int color)\n
Parameters var int startPosPtr
Pointer to the float array with world coordinates of the starting point of the line var int endPosPtr
Pointer to the float array with world coordinates of the ending point of the line var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawline3","title":"DrawLine3
","text":"DrawLine3
DrawLine
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawLine3(var int x1, var int y1, var int z1,var int x2, var int y2, var int z2,var int color)\n
Parameters var int x1, y1, z1
X, Y, and Z coordinates of the starting point of the line var int x2, y2, z2
X, Y, and Z coordinates of the ending point of the line var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawlineaddr","title":"DrawLineAddr
","text":"DrawLineAddr
DrawLine
, but with the address of a line as parameter.
func int DrawLineAddr(var int linePtr, var int color)\n
Parameters var int linePtr
Pointer to the float array array with six values (startAndEndPos[6]) var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateline","title":"UpdateLine
","text":"UpdateLine
Changes the coordinates of a specific line.
func void UpdateLine(var int hndl, var int startPosPtr, var int endPosPtr)\n
Parameters var int hndl
Handle returned from DrawLine
var int startPosPtr
Pointer to an integer float array with world coordinates of the starting point of the line var int endPosPtr
Pointer to an integer float array with world coordinates of the ending point of the line "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateline3","title":"UpdateLine3
","text":"UpdateLine3
UpdateLine
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateLine3(var int hndl,var int x1, var int y1, var int z1,var int x2, var int y2, var int z2)\n
Parameters var int hndl
Handle returned from DrawLine
var int x1, y1, z1
X, Y, and Z coordinates of the starting point of the line var int x2, y2, z2
X, Y, and Z coordinates of the ending point of the line "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatelineaddr","title":"UpdateLineAddr
","text":"UpdateLineAddr
UpdateLine
, but with the address of a line as parameter.
func void UpdateLineAddr(var int hndl, var int linePtr)\n
Parameters var int hndl
Handle returned from DrawLine
var int linePtr
Pointer to an integer float array with six values (startAndEndPos[6]) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setlinecolor","title":"SetLineColor
","text":"SetLineColor
Changes the color of a specific line.
func void SetLineColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawLine
var int color
New color of the line as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseline","title":"EraseLine
","text":"EraseLine
Deletes a line from the world and the handle.
func void EraseLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#linevisible","title":"LineVisible
","text":"LineVisible
Returns whether a line is visible.
func int LineVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
Return value
The function returns TRUE
if the line is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showline","title":"ShowLine
","text":"ShowLine
Displays the line.
func void ShowLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hideline","title":"HideLine
","text":"HideLine
Hides the line.
func void HideLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#toggleline","title":"ToggleLine
","text":"ToggleLine
Changes the visibility of a line. If displayed - hide, if hidden - display.
func void ToggleLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#sphere","title":"Sphere","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphere","title":"DrawSphere
","text":"DrawSphere
Creates and draws a new sphere (visualized as a circle) and returns its handle.
func int DrawSphere(var int centerPosPtr, var int radius, var int color)\n
Parameters var int centerPosPtr
Pointer to an integer float array with world coordinates of the sphere's center (centerPos[3]
) var int radius
Radius of the sphere as an integer float var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphere3","title":"DrawSphere3
","text":"DrawSphere3
DrawSphere
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawSphere3(var int x1, var int y1, var int z1, var int radius, var int color)\n
Parameters var int x1, y1, z1
World coordinates of the sphere's center var int radius
Radius of the sphere as an integer float var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphereaddr","title":"DrawSphereAddr
","text":"DrawSphereAddr
DrawSphere
, but with the address of a sphere as a parameter.
func int DrawSphereAddr(var int spherePtr, var int color)\n
Parameters var int spherePtr
Pointer to a zTBSphere3D
structure var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphere","title":"UpdateSphere
","text":"UpdateSphere
Changes the coordinates and/or size of an existing sphere.
func void UpdateSphere(var int hndl, var int centerPosPtr, var int radius)\n
Parameters var int hndl
Handle returned from DrawSphere
var int centerPosPtr
Pointer to an integer float array with world coordinates of the sphere's center (centerPos[3]
) var int radius
Radius of the sphere as an integer float "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphere3","title":"UpdateSphere3
","text":"UpdateSphere3
UpdateSphere
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateSphere3(var int hndl, var int x1, var int y1, var int z1, var int radius)\n
Parameters var int hndl
Handle returned from DrawSphere
var int x1, y1, z1
World coordinates of the sphere's center var int radius
Radius of the sphere as an integer float "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphereaddr","title":"UpdateSphereAddr
","text":"UpdateSphereAddr
UpdateSphere
, but with the address of a sphere as a parameter.
func void UpdateSphereAddr(var int hndl, var int spherePtr)\n
Parameters var int hndl
Handle returned from DrawSphere
var int spherePtr
Pointer to a zTBSphere3D
structure "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setspherecolor","title":"SetSphereColor
","text":"SetSphereColor
Changes the color of a specific sphere.
func void SetSphereColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawSphere
var int color
New color of the sphere as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#erasesphere","title":"EraseSphere
","text":"EraseSphere
Deletes a sphere from the world and its handle.
func void EraseSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#spherevisible","title":"SphereVisible
","text":"SphereVisible
Returns whether a sphere is visible.
func int SphereVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
Return value
The function returns TRUE
if the sphere is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showsphere","title":"ShowSphere
","text":"ShowSphere
Displays the sphere.
func void ShowSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hidesphere","title":"HideSphere
","text":"HideSphere
Hides the sphere.
func void HideSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#togglesphere","title":"ToggleSphere
","text":"ToggleSphere
Changes the visibility of a sphere. If displayed - hide, if hidden - display.
func void ToggleSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#bounding-box","title":"Bounding Box","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbbox","title":"DrawBBox
","text":"DrawBBox
Creates and draws a new bounding box and returns its handle.
func int DrawBBox(var int startPosPtr, var int endPosPtr, var int color)\n
Parameters var int startPosPtr
Pointer to an integer float array with world coordinates of the bounding box's first point (startPos[3]
) var int endPosPtr
Pointer to an integer float array with world coordinates of the bounding box's second point (endPos[3]
) var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbbox3","title":"DrawBBox3
","text":"DrawBBox3
DrawBBox
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawBBox3(var int x1, var int y1, var int z1, var int x2, var int y2, var int z2, var int color)\n
Parameters var int x1, y1, z1
World coordinates of the bounding box's first point var int x2, y2, z2
World coordinates of the bounding box's second point var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbboxaddr","title":"DrawBBoxAddr
","text":"DrawBBoxAddr
DrawBBox
, but with the address of a bounding box as a parameter.
func int DrawBBoxAddr(var int bboxPtr, var int color)\n
Parameters var int bboxPtr
Pointer to an integer float array with six values (startAndEndPos[6]) var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebbox","title":"UpdateBBox
","text":"UpdateBBox
Changes the coordinates of an existing bounding box.
func void UpdateBBox(var int hndl, var int startPosPtr, var int endPosPtr)\n
Parameters var int hndl
Handle returned from DrawBBox
var int startPosPtr
Pointer to an integer float array with world coordinates of the bounding box's first point (startPos[3]
) var int endPosPtr
Pointer to an integer float array with world coordinates of the bounding box's second point (endPos[3]
) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebbox3","title":"UpdateBBox3
","text":"UpdateBBox3
UpdateBBox
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateBBox3(var int hndl, var int x1, var int y1, var int z1, var int x2, var int y2, var int z2)\n
Parameters var int hndl
Handle returned from DrawBBox
var int x1, y1, z1
World coordinates of the bounding box's first point var int x2, y2, z2
World coordinates of the bounding box's second point "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebboxaddr","title":"UpdateBBoxAddr
","text":"UpdateBBoxAddr
UpdateBBox
, but with the address of a bounding box as a parameter.
func void UpdateBBoxAddr(var int hndl, var int bboxPtr)\n
Parameters var int hndl
Handle returned from DrawBBox
var int bboxPtr
Pointer to an integer float array with six values (startAndEndPos[6]) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setbboxcolor","title":"SetBBoxColor
","text":"SetBBoxColor
Changes the color of a specific bounding box.
func void SetBBoxColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawBBox
var int color
New color of the bounding box as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#erasebbox","title":"EraseBBox
","text":"EraseBBox
Deletes a bounding box from the world and its handle.
func void EraseBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#bboxvisible","title":"BBoxVisible
","text":"BBoxVisible
Returns whether a bounding box is visible.
func int BBoxVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
Return value
The function returns TRUE
if the bounding box is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showbbox","title":"ShowBBox
","text":"ShowBBox
Displays the bounding box.
func void ShowBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hidebbox","title":"HideBBox
","text":"HideBBox
Hides the bounding box.
func void HideBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#togglebbox","title":"ToggleBBox
","text":"ToggleBBox
Changes the visibility of a bounding box. If displayed - hide, if hidden - display.
func void ToggleBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#oriented-bounding-box","title":"Oriented Bounding Box","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawobboxaddr","title":"DrawOBBoxAddr
","text":"DrawOBBoxAddr
Creates and draws a new oriented bounding box based on the address of an oriented bounding box and returns its handle.
func int DrawOBBoxAddr(var int oBBoxPtr, var int color)\n
Parameters var int oBBoxPtr
Pointer to a zCOBBox3D
structure var int color
Color of the oriented bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the oriented bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateobboxaddr","title":"UpdateOBBoxAddr
","text":"UpdateOBBoxAddr
Changes the coordinates and orientation of an existing oriented bounding box.
func void UpdateOBBoxAddr(var int hndl, var int oBBoxPtr)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
var int oBBoxPtr
Pointer to a zCOBBox3D
structure "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setobboxcolor","title":"SetOBBoxColor
","text":"SetOBBoxColor
Changes the color of a specific oriented bounding box.
func void SetOBBoxColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
var int color
New color of the oriented bounding box as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseobbox","title":"EraseOBBox
","text":"EraseOBBox
Deletes an oriented bounding box from the world and its handle.
func void EraseOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#obboxvisible","title":"OBBoxVisible
","text":"OBBoxVisible
Returns whether an oriented bounding box is visible.
func int OBBoxVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
Return value
The function returns TRUE
if the oriented bounding box is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showobbox","title":"ShowOBBox
","text":"ShowOBBox
Displays the oriented bounding box.
func void ShowOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hideobbox","title":"HideOBBox
","text":"HideOBBox
Hides the oriented bounding box.
func void HideOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#toggleobbox","title":"ToggleOBBox
","text":"ToggleOBBox
Changes the visibility of an oriented bounding box. If displayed - hide, if hidden - display.
func void ToggleOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseall","title":"EraseAll
","text":"EraseAll
Deletes all draw elements and their handles from the world.
func void EraseAll()\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#examples","title":"Examples","text":"World coordinates are not particularly informative. This package aims to help and allows visualizing world coordinates in the form of lines, spheres (as circles), bounding boxes, and oriented bounding boxes in three-dimensional space.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#visualizing-straight-line-to-an-npc","title":"Visualizing Straight Line to an NPC","text":"To draw a line between two NPCs, you only need the coordinates of the two NPCs.
func void Example_1() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var int point1[3];\n point1[0] = her.trafoObjToWorld[3];\n point1[1] = her.trafoObjToWorld[7];\n point1[2] = her.trafoObjToWorld[11];\n\n var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);\n var int point2[3];\n point2[0] = oth.trafoObjToWorld[3];\n point2[1] = oth.trafoObjToWorld[7];\n point2[2] = oth.trafoObjToWorld[11];\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawLine(_@(point1), _@(point2), zCOLOR_GREEN);\n } else {\n UpdateLine(hndl, _@(point1), _@(point2));\n };\n};\n
This function can now be called continuously using FrameFunction
to continuously adjust the straight line according to the positions of the characters.
FF_Apply(Example_1);\n
Alternatively, you can write the function as follows:
func void Example_1() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawLine3(her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],\n oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11],\n zCOLOR_GREEN);\n } else {\n UpdateLine3(hndl, her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],\n oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11]);\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#visualizing-a-distance-of-5-meters","title":"Visualizing a Distance of 5 Meters","text":"It becomes more interesting when dealing with \"abstract\" coordinates. For instance, you can visualize a \"safety distance\" around the player using a bounding box or a sphere, to check AI reactions at certain distances.
//*******************\n// Bounding Box\n//*******************\nfunc void Example_2() {\n var zCVob her; her = Hlp_GetNpc(hero);\n\n // Safety distance around the player (5 meters)\n var int distance; distance = mkf(500);\n\n // Lower corner of the bounding box\n var int point1[3];\n point1[0] = subf(her.trafoObjToWorld[3], distance);\n point1[1] = subf(her.trafoObjToWorld[7], distance);\n point1[2] = subf(her.trafoObjToWorld[11], distance);\n\n // Upper corner of the bounding box (diagonally opposite)\n var int point2[3];\n point2[0] = addf(her.trafoObjToWorld[3], distance);\n point2[1] = addf(her.trafoObjToWorld[7], distance);\n point2[2] = addf(her.trafoObjToWorld[11], distance);\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawBBox(_@(point1), _@(point2), zCOLOR_BLUE);\n } else {\n UpdateBBox(hndl, _@(point1), _@(point2));\n };\n};\n
To draw a sphere with a radius of 5 meters centered at a specific point, you only need the coordinates of the sphere's center.
//*******************\n// Sphere\n//*******************\nfunc void Example_2() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var int centerPoint[3];\n centerPoint[0] = her.trafoObjToWorld[3];\n centerPoint[1] = her.trafoObjToWorld[7];\n centerPoint[2] = her.trafoObjToWorld[11];\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawSphere(_@(centerPoint), 500, zCOLOR_BLUE);\n } else {\n UpdateSphere(hndl, _@(centerPoint), 500);\n };\n};\n
Similarly, you could continuously update the bounding box/sphere using a FrameFunction
.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#changing-color-or-hidingdeleting-draw-elements","title":"Changing Color or Hiding/Deleting Draw Elements","text":"If you want to visualize an AI reaction, for example, you can change the color. Color values can be created using the RGBA
function based on RGB values.
func void ObserveIntruder(var int hndl, var C_NPC oth) {\n if (Npc_HasDetectedNpc(oth, hero)) {\n // Color is now red, position and size of the bounding box remain unchanged\n SetBBoxColor(hndl, zCOLOR_RED); // zCOLOR_RED == RGBA(255, 0, 0, 255)\n };\n};\n
Draw elements can also be easily hidden or completely deleted.
func void CheckDialog(var int hndl) {\n if (!InfoManager_HasFinished()) {\n // Hide bounding box during dialogs\n HideBBox(hndl);\n\n // EraseBBox(hndl); // Or delete including the handle\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/","title":"EventHandler","text":""},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventhandler","title":"EventHandler","text":"Info
Dependencies: - PermMem Implementation: EventHandler.d on GitHub
This package allows to create new events and trigger them at desired times. The Gamestate package already uses it.
Warning
The EventHandler requires some basic understanding of the PermMem. The documentation can be found here.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#initialization","title":"Initialization","text":"Initialize with LeGo_EventHandler
flag.
LeGo_Init(LeGo_EventHandler);\n
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_create","title":"Event_Create
","text":"Event_Create
Creates a new event and returns a handle to it.
func int Event_Create()\n
Return value The function returns a new PermMem handle to an event.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_delete","title":"Event_Delete
","text":"Event_Delete
Alias to PermMem delete
. Cleans up the handle.
func void Event_Delete(var int event)\n
Parameters var int event
Handle returned from Event_Create
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_empty","title":"Event_Empty
","text":"Event_Empty
Checks whether the event is \"empty\", i.e. nothing will happen after its execution.
func int Event_Empty(var int event)\n
Parameters var int event
Handle returned from Event_Create
Return value
The function returns TRUE
if event is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_has","title":"Event_Has
","text":"Event_Has
Checks if function
is added to the event.
func int Event_Has(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_add","title":"Event_Add
","text":"Event_Add
Adds an event handler function. The handler is called after running Event_Execute
.
func void Event_Add(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_addonce","title":"Event_AddOnce
","text":"Event_AddOnce
Event_Add
but checks if the handler function is already added, to prevent duplicates.
func void Event_AddOnce(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_remove","title":"Event_Remove
","text":"Event_Remove
Removes the event handler function
from the event.
func void Event_Remove(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_execute","title":"Event_Execute
","text":"Event_Execute
Core of the package. Calls all functions registered via Event_Add
and Event_AddOnce
.
func void Event_Execute(var int event, var int data)\n
Parameters var int event
Handle returned from Event_Create
var int data
Int parameter passed to all executed functions "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#ptr-functions","title":"Ptr functions","text":"Tip
The pointer functions are used internally by the previous functions. If you created an event with Event_Create
use functions without Ptr
in the name, but if you created event with EventPtr_Create
use only Ptr
functions. The normal user will probably never need the pointer versions, however the choice, which one to use is yours.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_create","title":"EventPtr_Create
","text":"EventPtr_Create
Creates a new event and returns a pointer to it.
func int EventPtr_Create()\n
Return value The function returns a new PermMem pointer to an event.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_delete","title":"EventPtr_Delete
","text":"EventPtr_Delete
Alias to PermMem free
. Cleans up the pointer.
func void EventPtr_Delete(var int eventPtr)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_empty","title":"EventPtr_Empty
","text":"EventPtr_Empty
Checks whether the event is \"empty\", i.e. nothing will happen after its execution.
func int EventPtr_Empty(var int eventPtr)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
Return value
The function returns TRUE
if empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_has","title":"EventPtr_Has
","text":"EventPtr_Has
Checks if function
is added to an event.
func int EventPtr_Has(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_hasi","title":"EventPtr_HasI
","text":"EventPtr_HasI
EventPtr_Has
but with function ID instead of pointer. Used mainly internally.
func int EventPtr_HasI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_add","title":"EventPtr_Add
","text":"EventPtr_Add
Adds an event handler function. The handler is called after running EventPtr_Execute
.
func void EventPtr_Add(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addi","title":"EventPtr_AddI
","text":"EventPtr_AddI
EventPtr_Add
but with function ID instead of pointer. Used mainly internally.
func void EventPtr_AddI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addonce","title":"EventPtr_AddOnce
","text":"EventPtr_AddOnce
Event_Add
but checks if function is already added, to prevent duplicates.
func void EventPtr_AddOnce(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addoncei","title":"EventPtr_AddOnceI
","text":"EventPtr_AddOnceI
EventPtr_AddI
but checks if function is already added, to prevent duplicates.
func void EventPtr_AddOnceI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_remove","title":"EventPtr_Remove
","text":"EventPtr_Remove
Removes a function from the event's call list.
func void EventPtr_Remove(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_removei","title":"EventPtr_RemoveI
","text":"EventPtr_RemoveI
EventPtr_Remove
but with function ID instead of pointer. Used mainly internally.
func void EventPtr_RemoveI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_execute","title":"EventPtr_Execute
","text":"EventPtr_Execute
Core of the package. Calls all functions registered via EventPtr_Add
and EventPtr_AddOnce
.
func void EventPtr_Execute(var int eventPtr, var int data)\n
var int eventPtr
Pointer returned from EventPtr_Create
var int data
Int parameter passed to all executed functions "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#examples","title":"Examples","text":"Note
This article has no built-in examples, but the best way to understand how EventHandler works is reading source code of the Gamestate package.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/","title":"FrameFunctions","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#framefunctions","title":"FrameFunctions","text":"Info
Dependencies: - Floats - PermMem - HookEngine - Timer Implementation: FrameFunctions.d on GitHub
The FrameFunctions package allows to call any number of functions called on every frame, or every specified time delay.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#initialization","title":"Initialization","text":"Initialize with LeGo_FrameFunctions
flag.
LeGo_Init(LeGo_FrameFunctions);\n
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_apply","title":"FF_Apply
","text":"FF_Apply
Adds the Daedalus function function
to the running FrameFunctions list. function
is called each frame.
func void FF_Apply(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applygt","title":"FF_ApplyGT
","text":"FF_ApplyGT
Adds the Daedalus function function
to the running FrameFunctions list. function
is called every frame except when the game is paused.
func void FF_ApplyGT(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applydata","title":"FF_ApplyData
","text":"FF_ApplyData
Adds the Daedalus function function
to the running FrameFunctions list. The integer parameter data
is passed to the function function
.
func void FF_ApplyData(var func function, var int data)\n
Parameters var func function
Name of the function. var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyext","title":"FF_ApplyExt
","text":"FF_ApplyExt
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times.
func void FF_ApplyExt(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextgt","title":"FF_ApplyExtGT
","text":"FF_ApplyExtGT
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. Gets called only when the game is not paused.
func void FF_ApplyExtGT(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextdata","title":"FF_ApplyExtData
","text":"FF_ApplyExtData
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. The integer parameter data
is passed to the function function
.
func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function. var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextdatagt","title":"FF_ApplyExtDataGT
","text":"FF_ApplyExtDataGT
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. The integer parameter data
is passed to the function function
. Gets called only when the game is not paused.
func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function. var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonce","title":"FF_ApplyOnce
","text":"FF_ApplyOnce
Alias to FF_Apply, which only adds the function once, even after multiple calls.
func void FF_ApplyOnce(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyoncegt","title":"FF_ApplyOnceGT
","text":"FF_ApplyOnceGT
Alias to FF_ApplyGT, which only adds the function once, even after multiple calls. Loop doesn't run if the game is paused.
func voidoften FF_ApplyOnceGT(var func function)\n
Parameters var func function
Name of the function. "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyoncedata","title":"FF_ApplyOnceData
","text":"FF_ApplyOnceData
Alias to FF_ApplyData, which only adds the function with the specified parameter once, even after multiple calls.
func void FF_ApplyOnceData(var func function, var int data)\n
Parameters var func function
Name of the function. var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceext","title":"FF_ApplyOnceExt
","text":"FF_ApplyOnceExt
Alias to FF_ApplyExt, which adds the function only once, after repeated calls.
func void FF_ApplyOnceExt(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceextgt","title":"FF_ApplyOnceExtGT
","text":"FF_ApplyOnceExtGT
Alias to FF_ApplyExtGT, which adds the function only once after repeated calls. Loop doesn't run if the game is paused.
func void FF_ApplyOnceExtGT(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceextdata","title":"FF_ApplyOnceExtData
","text":"FF_ApplyOnceExtData
Alias to FF_ApplyExtData, which adds the function with the specified parameter only once, after repeated calls.
func void FF_ApplyOnceExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_active","title":"FF_Active
","text":"FF_Active
Checks whether the function
is active.
func int FF_Active(var func function)\n
Parameters var func function
Name of the function Return value The function returns TRUE
if the function is active, FALSE
if it is not.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_activedata","title":"FF_ActiveData
","text":"FF_ActiveData
Checks whether the function
with the specified data
is active.
func int FF_ActiveData(var func function, var int data)\n
Parameters var func function
Name of the function var int data
Value previously passed to the function Return value The function returns TRUE
if the function is active, FALSE
if it is not.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_remove","title":"FF_Remove
","text":"FF_Remove
Stops a specific FrameFunction.
func void FF_Remove(var func function)\n
Parameters var func function
Name of the stopped function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_removeall","title":"FF_RemoveAll
","text":"FF_RemoveAll
Stops all intsnces of a specific FrameFunction.
func void FF_RemoveAll(var func function)\n
Parameters var func function
Name of the stopped function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_removedata","title":"FF_RemoveData
","text":"FF_RemoveData
Stops a specific FrameFunction, with the specified value (see FF_ApplyExtData
).
func void FF_RemoveData(var func function, var int data)\n
Parameters var func function
Name of the stopped function var int data
Value previously passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#a-function-called-every-frame","title":"A function called every frame","text":"In this example function MyFunc
will be executed on every frame.
func void Example1()\n{\n FF_Apply(MyFunc);\n};\n\nfunc void MyFunc() {};\n
After the Example1
function is executed the function MyFunc
is called on every frame. The easiest and best way to run a function from the beginning is to call FF-Apply
directly in the Init_Global
(under LeGo_Init
), there is a small problem: If the game is loaded, Init_Global
is called a second time, the function is added to the list again and is therefore always called twice.
To avoid this effect, you should check whether the function is already active:
func void Example1()\n{\n if(!FF_Active(MyFunc))\n {\n FF_Apply(MyFunc);\n };\n};\n
However, since LeGo version 2.2 there is an even more pleasant method to do this:
func void Example1()\n{\n FF_ApplyOnce(MyFunc);\n};\n
FF_ApplyOnce
function already implements the check for function activity."},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#calling-delayed-function","title":"Calling delayed function","text":"Create a function, that is called once after 3 seconds.
func void Example2()\n{\n FF_ApplyExt(MyFunc2, 3000, 1); // 3000 ms = 3 s, this function is called only once\n};\n\nfunc void MyFunc2() {};\n
There is also a Once
variant of this function, that prevents adding it twice into the frame function list.
func void Example2()\n{\n FF_ApplyOnceExt(MyFunc2, 3000, 1);\n};\n
Note
FF_ApplyExt(MyFunc, 0, -1)
is the same as FF_Apply(MyFunc)
.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#framefunction-with-timer","title":"FrameFunction with Timer","text":"Since LeGo 2.2, FrameFunctions package uses the Timer package, so it is possible to pause FrameFunctions at will:
func void Example3()\n{\n FF_ApplyOnceExt(MyFunc3, 4000, 2);\n};\n\nfunc void MyFunc3()\n{\n Timer_SetPaused(!Timer_GetPaused());\n};\n
This would pause the timer after 4 seconds and let it continue after 8 seconds. Warning
Because the timer doesn't run, the frame function execution is stopped as well. This script won't work. If the timer is to be paused, it must be paused outside FrameFunctions.
Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/","title":"Hashtables","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#hashtables","title":"Hashtables","text":"Info
Dependencies: - PermMem Implementation: Hashtable.d on GitHub
Hashtables package is an implementation of hashtables in Gothic. Currently (version 2.8.0) only integers are supported as keys. The Hashtables grow automatically.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_createsized","title":"HT_CreateSized
","text":"HT_CreateSized
Generates a hashtable of the specified size.
func int HT_CreateSized(var int size)\n
Parameters var int size
Size of the hashtable to be created Return value
The function returns a handle to the created hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_create","title":"HT_Create
","text":"HT_Create
Generates a standard size hashtable.
func int HT_Create()\n
Return value The function returns a handle to the created hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_insert","title":"HT_Insert
","text":"HT_Insert
Inserts a value into the Hashtable.
func void HT_Insert(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The value to be inserted var int key
The key associated with the value "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_resize","title":"HT_Resize
","text":"HT_Resize
Changes the size of the hashtable (usually not necessary as it happens automatically).
func void HT_Resize(var int handle, var int size)\n
Parameters var int handle
Handle of a hashtable var int size
The new size of the hashtable "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_get","title":"HT_Get
","text":"HT_Get
Reads a value from the hashtable.
func int HT_Get(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key whose value is to be read Return value
The function returns the value associated with the key.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_has","title":"HT_Has
","text":"HT_Has
Checks if the key already exist in hashtable.
func int HT_Has(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key to be checked Return value The function returns TRUE
if the key exist, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_remove","title":"HT_Remove
","text":"HT_Remove
Removes a key from the hashtable.
func void HT_Remove(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key to be removed "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_change","title":"HT_Change
","text":"HT_Change
Changes the value of a key already existing in the hashtable.
func void HT_Change(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The new value var int key
The key whose value is to be changed "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_insertorchange","title":"HT_InsertOrChange
","text":"HT_InsertOrChange
Inserts a value into the Hashtable, or changes the value if the key already exist into hashtable.
func void HT_InsertOrChange(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The new value var int key
The key whose value is to be changed or associated with the value. "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_getnumber","title":"HT_GetNumber
","text":"HT_GetNumber
Returns the number of entries in a hashtable.
func int HT_GetNumber(var int handle)\n
Parameters var int handle
Handle of a hashtable Return value
The function returns the number of entries in the hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_foreach","title":"HT_ForEach
","text":"HT_ForEach
Performs a function for each value pair in the hashtable.
func void HT_ForEach(var int handle, var func fnc)\n
Parameters var int handle
Handle of a hashtable var func fnc
A function with signature void (int key, int val)
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_destroy","title":"HT_Destroy
","text":"HT_Destroy
Deletes the hashtable.
func void HT_Destroy(var int handle)\n
Parameters var int handle
The handle of the hashtable to be deleted "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#simple-operations","title":"Simple operations","text":"func void PrintKeyValuePair(var int key, var int val)\n{\n Print(ConcatStrings(ConcatStrings(\"Key: \", IntToString(key)), ConcatStrings(\", Value: \", IntToString(val))));\n};\n\nfunc void example()\n{\n // Create a new hashtable\n var int hashtableHandle; hashtableHandle = HT_Create();\n\n // Insert values into the hashtable\n HT_Insert(hashtableHandle, 42, 1);\n HT_Insert(hashtableHandle, 23, 2);\n HT_Insert(hashtableHandle, 56, 3);\n\n // Get a value from the hashtable\n var int value; value = HT_Get(hashtableHandle, 2);\n Print(ConcatStrings(\"Value associated with key 2: \", IntToString(value)));\n\n // Check if a key exists in the hashtable\n if (HT_Has(hashtableHandle, 3))\n {\n Print(\"Key 3 exists in the hashtable.\");\n }\n else\n {\n Print(\"Key 3 does not exist in the hashtable.\");\n };\n\n // Remove a key from the hashtable\n HT_Remove(hashtableHandle, 1);\n\n // Change the value associated with a key\n HT_Change(hashtableHandle, 99, 3);\n\n // Insert a value or change it if the key exists\n HT_InsertOrChange(hashtableHandle, 123, 4);\n\n // Get the number of entries in the hashtable\n var int numEntries; numEntries = HT_GetNumber(hashtableHandle);\n Print(ConcatStrings(\"Number of entries in the hashtable: \", IntToString(numEntries)));\n\n\n // Iterate through the hashtable and print key-value pairs\n // Function from top of the example is used here\n HT_ForEach(hashtableHandle, PrintKeyValuePair);\n\n // Destroy the hashtable\n HT_Destroy(hashtableHandle);\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/","title":"HookDaedalus","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalus","title":"HookDaedalus","text":"Info
Dependencies: - None Implementation: HookDaedalus.d on GitHub
This package allows hooking daedalus functions. The principle is similar HookEngine. We have a function (hooked function) into which we would like to hook another function (hook function).
Tip
Having to hook a Daedalus function should be pretty rare, because you can simply adjust the corresponding function. However, it may become necessary in some contexts.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfunc","title":"HookDaedalusFunc
","text":"HookDaedalusFunc
Hooks the function.
func void HookDaedalusFunc(var func hooked, var func hook)\n
Parameters var func hooked
Hooked function var func hook
Hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfuncf","title":"HookDaedalusFuncF
","text":"HookDaedalusFuncF
Alias to the HookDaedalusFunc
function.
func void HookDaedalusFuncF(var func hooked, var func hook)\n
Parameters var func hooked
Hooked function var func hook
Hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfunci","title":"HookDaedalusFuncI
","text":"HookDaedalusFuncI
HookDaedalusFunc
but with function ID.
func void HookDaedalusFuncI(var int hookedID, var int hookID)\n
Parameters var int hookedID
ID of hooked function var int hookID
ID of hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfuncs","title":"HookDaedalusFuncS
","text":"HookDaedalusFuncS
HookDaedalusFunc
but with function name.
func void HookDaedalusFuncS(var string hookedName, var string hookName)\n
Parameters var string hookedName
Name of hooked function var string hookName
Name of hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#ishookd","title":"IsHookD
","text":"IsHookD
Checks whether a function is already hooking another. Each function can be hooked any number of times, but each function can only hook one other.
func int IsHookD(var int funcID)\n
Parameters var int funcID
Symbol index of a hook function Return value
The function returns TRUE
if the function is already hooking another, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#continuecall","title":"ContinueCall
","text":"ContinueCall
Continues the program run with the original function.
func void ContinueCall()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passargumenti","title":"PassArgumentI
","text":"PassArgumentI
Passes an integer as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentI(var int i)\n
Parameters var int i
Integer argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passarguments","title":"PassArgumentS
","text":"PassArgumentS
Passes a string as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentS(var string s)\n
Parameters var string s
String argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passargumentn","title":"PassArgumentN
","text":"PassArgumentN
Passes an instance as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentN(var instance n)\n
Parameters var instance n
Instance argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hook-before-function","title":"Hook before function","text":"We have a hook:
HookDaedalusFunc(hooked, hook);\n
The functions can look like that: func void hooked() \n{\n Print(\"Original function\");\n};\n\nfunc void hook() \n{\n Print(\"Our hook\");\n ContinueCall();\n};\n
The results should look like that Our hook\nOriginal function\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hook-after-function","title":"Hook after function","text":"We have the same hook:
HookDaedalusFunc(hooked, hook);\n
The functions are also similar, but the ContinueCall();
is called first: func void hooked() \n{\n Print(\"Original function\");\n};\n\nfunc void hook() \n{\n ContinueCall();\n Print(\"Our hook\");\n};\n
The results should look like that: Original function\nOur hook\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#arguments-and-return-values","title":"Arguments and return values","text":"If a function to be hooked expects parameters or returns a value, our hooking function should conform to that.
func int hooked(var int i) \n{\n Print(\"Original function\");\n return i+1;\n};\n\nfunc int hook(var int i) \n{\n Print(\"Our hook\");\n PassArgumentI(i);\n ContinueCall();\n};\n
In this case, we may not return the value at the end of the hook because the returned value will just stay on the stack. However, we shouldn't give up on calling PassArgumentI(i)
to ensure that it is still on top of the stack when the program continues with hooked."},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#manipulation-of-arguments-and-return-values","title":"Manipulation of arguments and return values","text":"We can also manipulate arguments and return values with our hook.
func int hook(var int i) \n{\n Print(\"Our hook\");\n PassArgumentI(i+1); // add 1\n ContinueCall();\n i = MEM_PopIntResult();\n i *= 2; // Multiply by 2\n return i;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#multiple-hooks","title":"Multiple hooks","text":"A function can be hooked any number of times, but each function can only hook one. New hooks are always inserted after the previous one. The following example illustrates this quite well.
HookDaedalusFunc(a, b); // B hooks A\nHookDaedalusFunc(a, c); // C hooks A to B\nHookDaedalusFunc(a, d); // D hooks A to C\n\nHookDaedalusFunc(c, b); // Ignored because B is already hooking a function\n\nvar int i; i = a(1);\n\n\n// Hooked function\nfunc int a(var int i) \n{\n MEM_Info(ConcatStrings(\"--- A: \", IntToString(i)));\n return i+1;\n};\n\n// First hook function:\n// Replaces `a` because the program run is not continued with ContinueCall\nfunc int b(var int i) \n{\n MEM_Info(ConcatStrings(\" -- B: \", IntToString(i)));\n return i;\n};\n\n// Second hook function:\n// Increments the argument before ContinueCall and then decrements the return value\nfunc int c(var int i) \n{\n MEM_Info(ConcatStrings(\" -> C: \", IntToString(i)));\n passArgumentI(i+1);\n ContinueCall();\n\n i = MEM_PopIntResult();\n i -= 1;\n MEM_Info(ConcatStrings(\" <- C: \", IntToString(i)));\n return i;\n};\n\n// Third hook function:\n// Increments the argument before ContinueCall and then decrements the return value\nfunc int d(var int i) \n{\n MEM_Info(ConcatStrings(\"-> D: \", IntToString(i)));\n passArgumentI(i+1);\n ContinueCall();\n\n i = MEM_PopIntResult();\n i -= 1;\n MEM_Info(ConcatStrings(\"<- D: \", IntToString(i)));\n return i;\n};\n\n// Output:\n// -> D: 1\n// -> C: 2\n// -- B: 3\n// <- C: 2\n// <- D: 1\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/","title":"HookEngine","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengine","title":"HookEngine","text":"Info
Dependencies: - None Implementation: HookEngine.d on GitHub
This package allows you to hook anywhere in an engine function to run your own Daedalus code.
Tip
Zerxes has provided a list of all engine functions for G2, including the number of bytes to fill in for oldInstr
. This list can be found here. This should make it possible for everyone to use the HookEngine effectively without IDA.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengine_1","title":"HookEngine
","text":"HookEngine
Attaches a function to an engine function address.
func void HookEngine(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengines","title":"HookEngineS
","text":"HookEngineS
Alias to the HookEngine
function.
func void HookEngineS(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookenginei","title":"HookEngineI
","text":"HookEngineI
Alias to HookEngine
with funcID.
func void HookEngineI(var int address, var int oldInstr, var int funcID)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var int funcID
ID of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookenginef","title":"HookEngineF
","text":"HookEngineF
Alias to HookEngine
with func
parameter.
func void HookEngineF(var int address, var int oldInstr, var func function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var func function
Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishooked","title":"IsHooked
","text":"IsHooked
Checks if a hook is already present at a given address.
func var int IsHooked(var int address)\n
Parameters var int address
Address of an engine function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishook","title":"IsHook
","text":"IsHook
Checks if a hook with a certain function is already present at an address.
func var int IsHook(var int address, var string function)\n
Parameters var int address
Address of an engine function. var string function
Name of a function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishooki","title":"IsHookI
","text":"IsHookI
Alias to IsHook
with a funcID as parameter.
func var int IsHookI(var int address, var int funcID)\n
Parameters var int address
Address of an engine function. var int funcID
ID of a function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishookf","title":"IsHookF
","text":"IsHookF
Alias to IsHook
with a function as parameter.
func var int IsHookF(var int address, var func function)\n
Parameters var int address
Address of an engine function. var func function
Daedalus function. Return value func
parameter The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehook","title":"RemoveHook
","text":"RemoveHook
Removes a function from a hook so that it is no longer called.
func void RemoveHook(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehooki","title":"RemoveHookI
","text":"RemoveHookI
Alias to RemoveHook
with funcID.
func void RemoveHook(var int address, var int oldInstr, var int funcID)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var int funcID
ID of Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehookf","title":"RemoveHookF
","text":"RemoveHookF
Alias for RemoveHook
with func
parameter.
func void RemoveHook(var int address, var int oldInstr, var func function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var func function
Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefunc","title":"ReplaceEngineFunc
","text":"ReplaceEngineFunc
Replaces an engine function with a Daedalus function.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var string replaceFunc)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var string replaceFunc
Name of a Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefunci","title":"ReplaceEngineFuncI
","text":"ReplaceEngineFuncI
Alias to ReplaceEngineFunc
with funcID.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var int funcID)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var int funcID
ID of a Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefuncf","title":"ReplaceEngineFuncF
","text":"ReplaceEngineFuncF
Alias to ReplaceEngineFunc
with func parameter.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var func function)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var func function
Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#disableenginefunc","title":"DisableEngineFunc
","text":"DisableEngineFunc
Makes sure that an engine function is simply skipped. This is very delicate and will not always work so easily.
func void DisableEngineFunc(var int address, var int thiscall_numparams)\n
Parameters var int address
Address of the engine function to be skipped. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hook_returnfalse","title":"Hook_ReturnFalse
","text":"Hook_ReturnFalse
Simple function to replace return FALSE
in hook.
func void Hook_ReturnFalse()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hook_returntrue","title":"Hook_ReturnTrue
","text":"Hook_ReturnTrue
Simple function to replace return TRUE
in hook.
func void Hook_ReturnTrue()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#registers","title":"Registers","text":"In addition the HookEngine package implement x86 32-bit registers that can be used to access hooked function parameters.
var int EAX;\nvar int ECX;\nvar int EDX;\nvar int EBX;\nvar int ESP;\nvar int EBP;\nvar int ESI;\nvar int EDI; \n
"},{"location":"zengin/scripts/extenders/lego/tools/int64/","title":"Int64","text":""},{"location":"zengin/scripts/extenders/lego/tools/int64/#int64","title":"Int64","text":"Info
Dependencies: - None Implementation: Int64.d on GitHub
Int64 implements basic arithmetic for 64-bit integers based on machine code (hence the function signatures are also in machine code style). Furthermore, Int64 offers the constructor int64@
for Int64 objects, but mk64 expects a pointer, not a handle.
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/int64/#mk64","title":"mk64
","text":"mk64
Writes lo
and hi
in one place (dest). Makes Int64, hi
has to be -1
for negative 32bit lo
.
func void mk64(var int dest, var int hi, var int lo)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. var int hi
High part of integer. var int lo
Low part of integer. Examples Function looks like that:
func void mk64(var int dest, var int lo, var int hi) {\n MEM_WriteInt(dest, lo);\n MEM_WriteInt(dest+4, hi);\n };\n
So if you want to get 9876543210
low part should be set to 1286608618
and the high part to 2
var int ptr; ptr = MEM_Alloc(8);\nvar int low; low = 1286608618;\nvar int high; high = 2;\nmk64(ptr, low, high);\n// ...\nMEM_Free(ptr);\n
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#neg64","title":"neg64
","text":"neg64
Negates the integer: *dest <- -(*dest)
func void neg64(var int dest)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#add64","title":"add64
","text":"add64
Adds src
to dest
: *dest <- *dest + *src
func void add64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#sub64","title":"sub64
","text":"sub64
Subtracts src
from dest
: *dest <- *dest - *src
func void sub64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#mul64","title":"mul64
","text":"mul64
Multiplies dest
by src
: *dest <- (*dest) * (*src)
func void mul64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#div64","title":"div64
","text":"div64
Divides dest
by src
: *dest <- *dest / *src
func void mul64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/interface/","title":"Interface","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#interface","title":"Interface","text":"Info
Dependencies: - AI_Function - Anim8 - HookEngine - PermMem Implementation: Interface.d on GitHub
This package offers a lot of useful functions to work with the 2D interface.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#initialization","title":"Initialization","text":"Initialize with LeGo_Interface
and LeGo_PrintS
flag.
LeGo_Init(LeGo_Interface | LeGo_PrintS);\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#sysgettime","title":"sysGetTime
","text":"sysGetTime
Better alternative for MEM_GetSysTime()
from Ikarus.
func int sysGetTime()\n
Return value The function returns elapsed time since game (system) startup.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#rgba","title":"RGBA
","text":"RGBA
Generates a full zColor
.
func int RGBA(var int r, var int g, var int b, var int a)\n
Parameters var int r
Red channel value (0..255) var int g
Green channel value (0..255) var int b
Blue channel value (0..255) var int a
Alpha (0..255, 0 = invisible) Return value
The function returns a zColor
object.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#changealpha","title":"ChangeAlpha
","text":"ChangeAlpha
Overrides the alpha value of a given zColor
.
func int ChangeAlpha(var int zCol, var int a)\n
Parameters var int zCol
zColor
to modify var int a
New alpha value Return value
The function returns a modified zColor
object.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#getalpha","title":"GetAlpha
","text":"GetAlpha
Returns the alpha value of a given zColor
.
func int GetAlpha(var int zCol)\n
Parameters var int zCol
zColor
to get alpha from "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtext","title":"Print_CreateText
","text":"Print_CreateText
Creates a new zCViewText
on the screen with PermMem that can be freely edited.
func int Print_CreateText(var string text, var string font)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text Return value
The function returns a handle to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtextptr","title":"Print_CreateTextPtr
","text":"Print_CreateTextPtr
Print_CreateText
but returns pointer to zCViewText
instead of handle.
func int Print_CreateTextPtr(var string text, var string font)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text Return value
The function returns a pointer to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtextptrcolored","title":"Print_CreateTextPtrColored
","text":"Print_CreateTextPtrColored
Print_CreateTextPtr
but with additional parameter to chose color of text.
func int Print_CreateTextPtrColored(var string text, var string font, var int color)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text var int color
zColor
e.g. generated with RGBA function Return value
The function returns a pointer to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_gettext","title":"Print_GetText
","text":"Print_GetText
Returns zCViewText
instance from handle.
func zCViewText Print_GetText(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_gettextptr","title":"Print_GetTextPtr
","text":"Print_GetTextPtr
Returns zCViewText
pointer from handle.
func int Print_GetTextPtr(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_deletetext","title":"Print_DeleteText
","text":"Print_DeleteText
Removes a zCViewText
from the screen.
func void Print_DeleteText(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
(form Print_CreateText
or Print_Ext
) "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_setalpha","title":"Print_SetAlpha
","text":"Print_SetAlpha
Changes the alpha value of a given zCViewText
.
func void Print_SetAlpha(var int hndl, var int a)\n
Parameters var int hndl
Handle to zCViewText
var int a
New alpha value "},{"location":"zengin/scripts/extenders/lego/tools/interface/#printptr_setalpha","title":"PrintPtr_SetAlpha
","text":"PrintPtr_SetAlpha
Print_SetAlpha
but with pointer to zCViewText
instead of handle.
func void PrintPtr_SetAlpha(var int ptr, var int a)\n
Parameters var int ptr
Pointer to zCViewText
var int a
New alpha value "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getscreensize","title":"Print_GetScreenSize
","text":"Print_GetScreenSize
Writes the current resolution to the Print_Screen array and the current aspect ratio to Print_Ratio variable.
func void Print_GetScreenSize()\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_screen","title":"Print_Screen
","text":"Print_Screen
An int array holding the current resolution. (Filled by Print_GetScreenSize
)
int Print_Screen[2];\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_ratio","title":"Print_Ratio
","text":"Print_Ratio
A float variable that holds the current aspect ratio. (Filled by Print_GetScreenSize
)
int Print_Ratio;\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#ps_vmax","title":"PS_VMax
","text":"PS_VMax
An int constant that holds the highest possible value of a virtual coordinate.
const int PS_VMax = 8192;\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_tovirtual","title":"Print_ToVirtual
","text":"Print_ToVirtual
Convents pixel position to a virtual position.
func int Print_ToVirtual(var int pxl, var int dim)\n
Parameters var int pxl
Pixel position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a virtual position of a given pixel position.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_tovirtualf","title":"Print_ToVirtualF
","text":"Print_ToVirtualF
Print_ToVirtual
but returns Ikarus float value instead of integer.
func int Print_ToVirtualF(var int pxl, var int dim)\n
Parameters var int pxl
Pixel position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a virtual position of a given pixel position as Ikarus float.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_topixel","title":"Print_ToPixel
","text":"Print_ToPixel
Convents virtual position to a pixel position.
func int Print_ToPixel(var int vrt, var int dim)\n
Parameters var int vrt
Virtual position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a pixel position of a given virtual position.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_topixelf","title":"Print_ToPixelF
","text":"Print_ToPixelF
Print_ToPixel
but returns Ikarus float value instead of integer.
func int Print_ToPixelF(var int vrt, var int dim)\n
Parameters var int vrt
Virtual position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a pixel position of a given virtual position as Ikarus float.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_toratio","title":"Print_ToRatio
","text":"Print_ToRatio
Gets the size in the specified dimension in ratioed by the screen.
func int Print_ToRatio(var int size, var int dim)\n
Parameters var int size
Size to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns size correctly calculated to the ratio.
Example If you have a view and the view you need to be a square of 400 units, you would do:
height = Print_ToRatio(400, PS_Y);\nwidth = 400;\n
This is because width is always the max in virtual coordinates - 8192 virtual points and the height has a different height based on the ratio, this function calculates it for you. PS_X
can be used in function, if you already have the height but need the width in the correct ratio.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_toradian","title":"Print_ToRadian
","text":"Print_ToRadian
Converts angle in degrees to radians.
func int Print_ToRadian(var int angle)\n
Parameters var int angle
Angle in degrees Return value
The function returns calculated angle in radians.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_todegree","title":"Print_ToDegree
","text":"Print_ToDegree
Converts angle in radians to degrees.
func int Print_ToDegree(var int angle)\n
Parameters var int angle
Angle in radians Return value
The function returns calculated angle in degrees.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontptr","title":"Print_GetFontPtr
","text":"Print_GetFontPtr
Returns a pointer to a zCFont
by its name.
func int Print_GetFontPtr(var string font)\n
Parameters var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontname","title":"Print_GetFontName
","text":"Print_GetFontName
Returns a name of a zCFont
from its pointer.
func string Print_GetFontName(var int fontPtr)\n
Parameters var int fontPtr
Pointer to font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getstringwidth","title":"Print_GetStringWidth
","text":"Print_GetStringWidth
Returns the width of a string in pixels.
func int Print_GetStringWidth(var string s, var string font)\n
Parameters var string s
Measured string var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getstringwidthptr","title":"Print_GetStringWidthPtr
","text":"Print_GetStringWidthPtr
Print_GetStringWidth
but with zCFont
pointer instead of name.
func int Print_GetStringWidthPtr(var string s, var int font)\n
Parameters var string s
Measured string var int font
zCFont
pointer "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontheight","title":"Print_GetFontHeight
","text":"Print_GetFontHeight
Returns the height of a string in pixels.
func int Print_GetFontHeight(var string font)\n
Parameters var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_ext","title":"Print_Ext
","text":"Print_Ext
Like the external PrintScreen
, writes a text on the screen, but with more options.
func int Print_Ext(var int x, var int y, var string text, var string font, var int color, var int time)\n
Parameters var int x
X coordinate on the screen (virtual) var int y
Y coordinate on the screen (virtual) var string text
Displayed text var string font
Name of font var int color
zColor
e.g. generated with RGBA function var int time
display time in milliseconds (-1 = permanent) Return value
If time == -1
, a valid handle is returned. If time != -1
, the print is only volatile and no handle is returned.
Example func void Example1()\n{\n // x, y, text, font, color, time\n Print_ExtPxl(2, 2, \"Text\", FONT_Screen, RGBA(255, 0, 0, 128), 500);\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_extpxl","title":"Print_ExtPxl
","text":"Print_ExtPxl
Print_Ext
but with pixel coordinates instead of virtual.
func int Print_ExtPxl(var int x, var int y, var string text, var string font, var int color, var int time)\n
Parameters var int x
X coordinate on the screen (pixel) var int y
Y coordinate on the screen (pixel) var string text
Displayed text var string font
Name of font var int color
zColor
e.g. generated with RGBA function var int time
display time in milliseconds (-1 = permanent) Return value
If time == -1
, a valid handle is returned. If time != -1
, the print is only volatile and no handle is returned.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestline","title":"Print_LongestLine
","text":"Print_LongestLine
Returns the longest line from text
as a string, using default line separator tilde ~
.
func string Print_LongestLine(var string text, var string font)\n
Parameters var string text
Measured text var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlineext","title":"Print_LongestLineExt
","text":"Print_LongestLineExt
Returns the longest line from text
as a string, but you specify new line separator.
func string Print_LongestLineExt(var string text, var string font, var string separator)\n
Parameters var string text
Measured text var string font
Name of font var string separator
New line separator "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlinelength","title":"Print_LongestLineLength
","text":"Print_LongestLineLength
Returns the longest line width in pixels, using default line separator tilde ~
.
func int Print_LongestLineLength(var string text, var string font)\n
Parameters var string text
Measured text var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlinelengthext","title":"Print_LongestLineLengthExt
","text":"Print_LongestLineLengthExt
Returns the longest line width in pixels, but allows you to specify new line separator.
func int Print_LongestLineLengthExt(var string text, var string font, var string separator)\n
Parameters var string text
Measured text var string font
Name of font var string separator
New line separator "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfield","title":"Print_TextField
","text":"Print_TextField
Creates a text field (view with text) using virtual coordinates.
func int Print_TextField(var int x, var int y, var string text, var string font, var int height)\n
Parameters var int x
X coordinate (virtual) var int y
Y coordinate (virtual) var string text
Text to be printed var string font
Name of font var int height
A specific line height
Return value
The function returns a text field pointer. Here is how it is used:
var zCView view; view = get(viewHndl);\nview.textLines_next = Print_TextField(x, y, text, FONT, fontHeight);\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfieldpxl","title":"Print_TextFieldPxl
","text":"Print_TextFieldPxl
Print_TextField
but with pixel coordinates.
func int Print_TextFieldPxl(var int x, var int y, var string text, var string font)\n
Parameters var int x
X coordinate (pixel) var int y
Y coordinate (pixel) var string text
Text to be printed var string font
Name of font Return value
The function returns a text field pointer. Look at the Print_TextField
return value to see an example.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfieldcolored","title":"Print_TextFieldColored
","text":"Print_TextFieldColored
Print_TextField
but you specify the color of text.
func int Print_TextFieldColored(var int x, var int y, var string text, var string font, var int height, var int color)\n
Parameters var int x
X coordinate (virtual) var int y
Y coordinate (virtual) var string text
Text to be printed var string font
Name of font var int height
A specific line height
var int color
zColor
e.g. generated with RGBA function Return value
The function returns a text field pointer. Look at the Print_TextField
return value to see an example.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#prints","title":"PrintS
","text":"PrintS
Same function as the external Print
, but with smooth animations. The effect can be changed as desired with the user constants.
func void PrintS(var string txt)\n
Parameters var string txt
Printed text "},{"location":"zengin/scripts/extenders/lego/tools/interface/#prints_ext","title":"PrintS_Ext
","text":"PrintS_Ext
PrintS
but with an additional parameter to choose the color of the text.
func void PrintS_Ext(var string txt, var int color)\n
Parameters var string txt
Printed text var int color
zColor
e.g. generated with RGBA function "},{"location":"zengin/scripts/extenders/lego/tools/interface/#ai_prints","title":"AI_PrintS
","text":"AI_PrintS
Version of PrintS
that enqueue in given NPCs AI queue.
func void AI_PrintS(var c_npc slf, var string txt)\n
Parameters var c_npc slf
NPC to whose AI queue the function is enqueued var string txt
Printed text "},{"location":"zengin/scripts/extenders/lego/tools/interface/#ai_prints_ext","title":"AI_PrintS_Ext
","text":"AI_PrintS_Ext
Version of PrintS_Ext
that enqueue in given NPCs AI queue.
func void AI_PrintS_Ext(var c_npc slf, var string txt, var int color)\n
Parameters var c_npc slf
NPC to whose AI queue the function is enqueued var string txt
Printed text var int color
zColor
e.g. generated with RGBA function "},{"location":"zengin/scripts/extenders/lego/tools/interface/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#manage-a-print-via-zcviewtext","title":"Manage a print via zCViewText","text":"It is also possible to create the text only via Print_CreateText and set it yourself. In this example, a text should fly over the image from left to right and be deleted again. The movement is handled by Anim8:
var int MyText;\nvar int MyAnim8;\nfunc void PrintMyScrollingText(var string text) {\n MyText = Print_CreateText(text, FONT_Screen); // We create an empty text item with the font FONT_Screen\n\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Now we get the empty text item in a zCViewText\n\n MyTextObject.posx = 1; // adjust position\n MyTextObject.posy = 1; // ATTENTION: These values are virtual, i.e.: 0 = far left, 8192 = far right (i.e. no pixel specification)\n // (But if I prefer to have pixel coordinates I could use e.g. Print_ToVirtual)\n MyTextObject.timed = false; // The text should not be timed (not disappear)\n\n // Anim8 will animate a text\n // First we need a new Anim8 object:\n MyAnim8 = Anim8_New(1, false); // Start position is 1 and this value is not a float\n\n Anim8(MyAnim8, 8192, 2000, A8_Constant); // Target Position is 8192, Duration is 2000 milliseconds, and Movement Form is Constant\n\n // Now all we need is a loop that matches the x value of the text to the value of Anim8:\n FF_Apply(ScrollMyText);\n};\n\nfunc void ScrollMyText() {\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Get the text as an object again\n\n // And now compare the values:\n MyTextObject.posx = Anim8_Get(MyAnim8);\n\n // When Anim8 is done with that, we end the loop and delete the text:\n if(Anim8_Empty(MyAnim8)) {\n Print_DeleteText(MyText);\n FF_Remove(ScrollMyText);\n // The Anim8 object must of course also be deleted. We don't need it anymore.\n Anim8_Delete(MyAnim8);\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#manage-a-print-via-zcviewtext-with-lego-22","title":"Manage a print via zCViewText with LeGo 2.2+","text":"In those days it was perhaps pleasant, but today it is no longer. Anim8 has seen a few improvements with LeGo 2.2 that make it much easier to create the same effect:
var int MyText;\nvar int MyAnim8;\nfunc void PrintMyScrollingText(var string text) {\n // Create and set text:\n MyText = Print_CreateText(text, FONT_Screen);\n\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText);\n\n MyTextObject.posx = 1;\n MyTextObject.posy = 1;\n\n MyTextObject.timed = false;\n\n // But now comes the trick: We use Anim8_NewExt, this allows us to set a \"Handler\" and \"Data\".\n MyAnim8 = Anim8_NewExt(1, ScrollMyText, MyText, false);\n\n // ScrollMyText is passed as the handler and MyText as the data.\n // In concrete terms, this means: ScrollMyText is always called\n // when Anim8 has recalculated the position.\n // Pass data and the new position as parameters. Let's see how it goes.\n\n // Set the animation again as usual:\n Anim8(MyAnim8, 8192, 2000, A8_Constant);\n\n // And this time no FrameFunction.\n // Instead, we tell Anim8 to clean up by itself when it's done:\n Anim8_RemoveIfEmpty(MyAnim8, true);\n\n // The text should also disappear by itself:\n Anim8_RemoveDataIfEmpty(MyAnim8, true);\n\n // Since MyText is a handle, this will work.\n // If MyText were a pointer, RemoveDataIfEmpty should not be activated, it would lead to an error message.\n};\n\nfunc void ScrollMyText(var int MyText, var int Position) {\n // Get the text as an object again\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText);\n\n // And now compare the values:\n MyTextObject.posx = Position;\n\n // Since Anim8 does the deleting itself, we don't have to worry about that.\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/","title":"ItemHelper","text":""},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#itemhelper","title":"ItemHelper","text":"Info
Dependencies: - None Implementation: ItemHelper.d on GitHub
This package is very simple - it retrieves a oCItem
pointer from an C_ITEM
instance valid for the current world and session.
Warning
Make sure every world has waypoint with name TOT
(\"dead\" in German). Ikarus & LeGo need this waypoint to spawn helper NPCs. This is especially important in Gothic 1 since G1 vanilla worlds do not have the TOT
waypoint.
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#itm_getptr","title":"Itm_GetPtr
","text":"Itm_GetPtr
func int Itm_GetPtr(var int instance)\n
Parameters var int instance
C_ITEM
instance to get the pointer of Return value The function returns oCItem
pointer of the C_ITEM
instance.
"},{"location":"zengin/scripts/extenders/lego/tools/list/","title":"List","text":""},{"location":"zengin/scripts/extenders/lego/tools/list/#list","title":"List","text":"Info
Dependencies: - None Implementation: List.d on GitHub
The List package is a collection of functions designed to simplify the handling of zCList
and zCListSort
lists in daedalus. It offers a range of functions for creating, manipulating, and querying lists.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/list/#functions","title":"Functions","text":"Note
All functions, expect List_Compare
come with an additional \"S\" at the end for objects of type zCListSort
. (Example: List_NodeS
.) Unlike most LeGo packages, pointers are used here, not handles!
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_create","title":"List_Create
","text":"List_Create
Creates a list with an initial value.
func int List_Create(var int data)\n
Parameters var int data
The value of the first list element. Return value
The function returns a pointer to the created list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_add","title":"List_Add
","text":"List_Add
Appends a value to the end of the list.
func void List_Add(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_addfront","title":"List_AddFront
","text":"List_AddFront
Adds a value before the first element of the list.
func void List_AddFront(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_addoffset","title":"List_AddOffset
","text":"List_AddOffset
Inserts a value between two list elements.
func void List_AddOffset(var int list, var int offset, var int data)\n
Parameters var int list
The list to be used. var int offset
The number of the list element after which the value is inserted. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_set","title":"List_Set
","text":"List_Set
Sets a list element to a specific value.
func void List_Set(var int node, var int data)\n
Parameters var int node
Pointer to a list element. var int data
The value to be written into the list element. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_get","title":"List_Get
","text":"List_Get
Retrieves the value of a list element.
func int List_Get(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of the list element. Return value
The function returns the value of the specified list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_node","title":"List_Node
","text":"List_Node
Returns a pointer to a list element.
func int List_Node(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of a list element. Return value
The function returns a pointer to the specified list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_length","title":"List_Length
","text":"List_Length
Returns the length of the list (number of all elements).
func int List_Length(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns the number of elements in the list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_haslength","title":"List_HasLength
","text":"List_HasLength
Checks if the list has the specified length.
func int List_HasLength(var int list, var int length)\n
Parameters var int list
The list to be used. var int length
The desired length. Return value
The function returns a boolean value indicating whether the list has the specified length or not.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_end","title":"List_End
","text":"List_End
Returns the last list element of the list.
func int List_End(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns a pointer to the last list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_concat","title":"List_Concat
","text":"List_Concat
Concatenates two lists.
func void List_Concat(var int list, var int list2)\n
Parameters var int list
The first list. var int list2
The second list. Its beginning is appended to the end of the first list. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_contains","title":"List_Contains
","text":"List_Contains
Returns the last list element with a specific value.
func int List_Contains(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to search for. Return value
The function returns the number of the last list element with the value data
.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_for","title":"List_For
","text":"List_For
Calls a function for each list element, passing a pointer to the list element as a parameter.
func void List_For(var int list, var string function)\n
Parameters var int list
The list to be used. var string function
Name of a function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_forf","title":"List_ForF
","text":"List_ForF
Similar to List_For
, but with a function parameter instead of a string.
func void ListForF(var int list, var func function)\n
Parameters var int list
The list to be used. var func function
The function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_fori","title":"List_ForI
","text":"List_ForI
Similar to List_For
, but with a function parameter instead of a string.
func void List_ForI(var int list, var int funcID)\n
Parameters var int list
The list to be used. var int funcID
ID of a function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_delete","title":"List_Delete
","text":"List_Delete
Deletes a list element. All subsequent elements shift position.
func void List_Delete(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of the list element to be deleted. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_destroy","title":"List_Destroy
","text":"List_Destroy
Destroys the entire list.
func void List_Destroy(var int list)\n
Parameters var int list
The list to be destroyed. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_toarray","title":"List_ToArray
","text":"List_ToArray
Returns a pointer to a memory area containing all values of the list.
func int List_ToArray(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns a memory area containing all the values of the list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_movedown","title":"List_MoveDown
","text":"List_MoveDown
Moves the specified list node down by one position in the list.
func void List_MoveDown(var int list, var int node)\n
Parameters var int list
The list in which the node is located. var int node
The node to be moved down. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_moveup","title":"List_MoveUp
","text":"List_MoveUp
Moves the specified list node up by one position in the list.
func void List_MoveUp(var int list, var int node)\n
Parameters var int list
The list in which the node is located. var int node
The node to be moved up. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_insertsorted","title":"List_InsertSorted
","text":"List_InsertSorted
Inserts a value into a sorted list while preserving the sort order.
func void List_InsertSorted(var int list, var int data, var func compare)\n
Parameters: var int list
The list to insert the value into. var int data
The value to be inserted. var func compare
A comparison function used to determine the sort order. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_compare","title":"List_Compare
","text":"List_Compare
func int List_Compare(var int data1, var int data2, var func compare)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. var func compare
One of comparison functions. Return value The function returns the return value of specified comparison function.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#comparison-functions","title":"Comparison Functions","text":"The following comparison functions can be used as the compare
parameter in the List_InsertSorted
and List_Compare
function:
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpascending","title":"List_CmpAscending
","text":"List_CmpAscending
Compares two integer values in ascending order.
func int List_CmpAscending(var int data1, var int data2)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. Return Value:
The function returns TRUE
if data1
is greater than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpdescending","title":"List_CmpDescending
","text":"List_CmpDescending
Compares two integer values in descending order.
func int List_CmpDescending(var int data1, var int data2)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. Return Value:
The function returns TRUE
if data1
is less than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpascendingunsigned","title":"List_CmpAscendingUnsigned
","text":"List_CmpAscendingUnsigned
Compares two unsigned integer values in ascending order.
func int List_CmpAscendingUnsigned(var int data1, var int data2)\n
Parameters: var int data1
The first unsigned integer value. var int data2
The second unsigned integer value. Return Value:
The function returns TRUE
if data1
is greater than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpdescendingunsigned","title":"List_CmpDescendingUnsigned
","text":"List_CmpDescendingUnsigned
Compares two unsigned integer values in descending order.
func int List_CmpDescendingUnsigned(var int data1, var int data2)\n
Parameters: var int data1
The first unsigned integer value. var int data2
The second unsigned integer value. Return Value:
The function returns TRUE
if data1
is less than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/locals/","title":"Locals","text":""},{"location":"zengin/scripts/extenders/lego/tools/locals/#locals","title":"Locals","text":"Info
Dependencies: - StringBuilder Implementation: Locals.d on GitHub
Daedalus doesn't offer any local variables, which can quickly lead to problems with recursive functions. The Locals package allows variables to be saved temporarily on a pseudo-stack. Locals is a very specific package. People who work normally with Daedalus will probably never need it. There is also the final
function, which can be used to emulate something similar to the final
clause in Java.
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/locals/#locals_1","title":"Locals
","text":"Locals
All that has to be done to enable the Locals
is to write this function at the beginning of the function that should receive \"real\" local variables.
func void locals()\n
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#final","title":"Final
","text":"Final
It is hard to explain how to use it, but very easy to understand once you've seen an example.
func int Final()\n
Example With final()
it is very easy to emulate Java's final
clause, i.e. a block of code can be specified, which is executed after this function is exited, regardless of when or where the function is exited.
func void testFinal()\n{\n if (final())\n {\n MEM_InfoBox(\"Final was called.\");\n };\n MEM_InfoBox(\"This will appear before Final\");\n};\n
Few lines of code say more than a thousand words."},{"location":"zengin/scripts/extenders/lego/tools/misc/","title":"Misc","text":""},{"location":"zengin/scripts/extenders/lego/tools/misc/#misc","title":"Misc","text":"Info
Dependencies: - Floats Implementation: Misc.d on GitHub
The Misc package introduces various helper functions that did not fit into any other package.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#constants","title":"Constants","text":"Misc package implements the phi
constant
const int phi = 1070141312; // PI/2\n
which is actually pi
divided by 2 saved as an ikarus float. Decimal: 1.5707...
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/misc/#atan2f","title":"atan2f
","text":"atan2f
Calculates the arcus tangent of an angle between the origin and (x, y) point.
func int atan2f(var int x, var int y)\n
Parameters var int x
X-coordinate var int y
Y-coordinate Return value
The function returns arcus tangent in radians as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#sin","title":"sin
","text":"sin
Calculates the sine of an angle given in radians.
func int sin(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns sine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#cos","title":"cos
","text":"cos
Calculates the cosine of an angle given in radians.
func int cos(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns cosine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#tan","title":"tan
","text":"tan
Calculates the tangent of an angle given in radians.
func int tan(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns tangent of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#asin","title":"asin
","text":"asin
Calculates the arcus sine.
func int asin(var int sine)\n
Parameters var int sine
The sine of an angle as a Ikarus float
Return value
The function returns arcus sine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#acos","title":"acos
","text":"acos
Calculates the arcus cosine
func int acos(var int cosine)\n
Parameters var int cosine
The cosine of an angle as a Ikarus float
Return value
The function returns arcus cosine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#distance2d","title":"distance2D
","text":"distance2D
Calculates the distance between two points on a two-dimensional plane.
func int distance2D(var int x1, var int x2, var int y1, var int y2)\n
Parameters var int x1
X-coordinate of the first point var int x2
X-coordinate of the second point var int y1
Y-coordinate of the first point var int y2
Y-coordinate of the second point Return value
The function returns the distance between the two points.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#distance2df","title":"distance2Df
","text":"distance2Df
Calculates the distance between two points on a two-dimensional plane but parameters and return values are Ikarus floats
.
func int distance2Df(var int x1, var int x2, var int y1, var int y2)\n
Parameters var int x1
X-coordinate of the first point var int x2
X-coordinate of the second point var int y1
Y-coordinate of the first point var int y2
Y-coordinate of the second point Return value
The function returns the distance between the two points as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/","title":"PermMem","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#permmem","title":"PermMem","text":"Info
Dependencies: - Saves - Locals Implementation: PermMem.d on GitHub
PermMem is a powerful package that allows classes (or instances) to be used permanently even after loading or restarting by saving them to the ASCII .ZEN
archive in the savegame directory. PermMem manages handles that are used to access instances, and provides various functions to manipulate these handles and instances.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#new","title":"new
","text":"new
Creates a handle to a new instance of inst
.
func int new(var int inst)\n
Parameters var int inst
A valid instance. Used as \"constructor\" Return value
The function returns a new, valid PermMem handle.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#create","title":"create
","text":"create
Similar to new
, but here a pointer is returned directly and not a handle. Caution! Not managed by PermMem!
func int create(var int inst)\n
Parameters var int inst
A valid instance. Used as \"constructor\" Return value
The function returns a pointer to the new instance.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#wrap","title":"wrap
","text":"wrap
\"Wraps\" a handle \"around\" a pointer so that the pointer can be used with any function that expects handles. Only conditionally managed by PermMem.
func int wrap(var int inst, var int ptr)\n
Parameters var int inst
A valid instance. Determines the type of the handle var int ptr
Pointer to wrap Return value
The function returns a handle with ptr
as content.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#clear","title":"clear
","text":"clear
Cleans the handle. After that it is invalid.
func void clear(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#release","title":"release
","text":"release
Frees the handle. The reserved memory is not deleted, the handle becomes invalid.
func void release(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#delete","title":"delete
","text":"delete
Cleans the handle just like clear
, only the destructor is also called.
func void delete(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#free","title":"free
","text":"free
Similar to delete
, only here a pointer is destroyed and not a handle. Caution! Not managed by PermMem!
func void free(var int ptr, var int inst)\n
Parameters var int ptr
The pointer to be cleaned var int inst
Instance used in create
function. "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#get","title":"get
","text":"get
Returns the instance of the handle.
func instance get(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#getptr","title":"getPtr
","text":"getPtr
Returns a pointer to instance of handle.
func int getPtr(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#setptr","title":"setPtr
","text":"setPtr
Sets the pointer of a handle.
func void setPtr(var int hndl, var int ptr)\n
Parameters var int hndl
Valid PermMem handle var int ptr
New pointer for handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#getinst","title":"getInst
","text":"getInst
Returns the instance used to create the given handle in new
function.
func int getInst(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#numhandles","title":"numHandles
","text":"numHandles
Returns the number of handles managed by PermMem.
func int numHandles()\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#sizeof","title":"sizeof
","text":"sizeof
Gets the size of the given instance's class.
func int sizeof(var int inst)\n
Parameters var int inst
Any instance Return value
The function returns the size of a given instance's class in bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#hlp_isvalidhandle","title":"Hlp_IsValidHandle
","text":"Hlp_IsValidHandle
Indicates whether the handle exists and is managed by PermMem.
func int Hlp_IsValidHandle(var int hndl)\n
Parameters var int hndl
PermMem's handle Return value
The function returns TRUE
if the handle is valid (managed by PermMem), FALSE
is returned otherwise.
Example The example function that use Hlp_IsValidHandle
is Bar_SetMax
form LeGo Bars package. The function first checks if the handle is valid, then gets the instance and changes its parameters.
func void Bar_SetMax(var int bar, var int max) \n{\n if(!Hlp_IsValidHandle(bar)) { return; };\n var _bar b; b = get(bar);\n b.valMax = max;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#foreachhndl","title":"foreachHndl
","text":"foreachHndl
Executes a function for each handle of an instance.
func void foreachHndl(var int inst, var func fnc)\n
Parameters var int inst
The function is called for this instance var int inst
This function is called. The signature is function(int handle)
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#hashndl","title":"hasHndl
","text":"hasHndl
Checks if PermMem has a handle of this instance.
func int hasHndl(var int inst)\n
Parameters var int inst
Instance to be checked Return value
The function returns TRUE
if the PermMem has a handle of this instance, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#mem_readstringarray","title":"MEM_ReadStringArray
","text":"MEM_ReadStringArray
Function moved to PermMem form Ikarus. Reads string from the array at the arrayAddress
.
func string MEM_ReadStringArray(var int arrayAddress, var int index)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns string from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_exists","title":"PM_Exists
","text":"PM_Exists
Checks if the specified field already exists in the archive. (used with archiver/unarchiver)
func int PM_Exists(var string name)\n
Parameters var string name
Name of the field Return value
The function returns TRUE
if the field exists in the archive, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#archiver","title":"Archiver","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveint","title":"PM_SaveInt
","text":"PM_SaveInt
Saves an integer to the archive.
func void PM_SaveInt (var string name, var int val)\n
Parameters var string name
Name of the field in saved archive var int val
Value of the saved integer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefloat","title":"PM_SaveFloat
","text":"PM_SaveFloat
Saves a daedalus float to the archive.
func void PM_SaveFloat (var string name, var int flt)\n
Parameters var string name
Name of the field in saved archive var int flt
Value of the saved float "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savestring","title":"PM_SaveString
","text":"PM_SaveString
Saves a string to the archive.
func void PM_SaveString (var string name, var string val)\n
Parameters var string name
Name of the field in saved archive var string val
Saved string "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncid","title":"PM_SaveFuncID
","text":"PM_SaveFuncID
Saves a function ID to the archive.
func void PM_SaveFuncID(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function ID "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncoffset","title":"PM_SaveFuncOffset
","text":"PM_SaveFuncOffset
Saves a function offset to the archive.
func void PM_SaveFuncOffset(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function offset "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncptr","title":"PM_SaveFuncPtr
","text":"PM_SaveFuncPtr
Saves a function pointer to the archive.
func void PM_SaveFuncPtr(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveclassptr","title":"PM_SaveClassPtr
","text":"PM_SaveClassPtr
Saves a pointer of a class to the archive.
func void PM_SaveClassPtr(var string name, var int ptr, var string className)\n
Parameters var string name
Name of the field in saved archive var int ptr
Saved pointer var string className
Name of the class of stored pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveclass","title":"PM_SaveClass
","text":"PM_SaveClass
Saves a class like PM_SaveClassPtr
.
func void PM_SaveClass(var string name, var int ptr, var string className)\n
Parameters var string name
Name of the field in saved archive var int ptr
Saved class pointer var string className
Name of the class of stored pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveintarray","title":"PM_SaveIntArray
","text":"PM_SaveIntArray
Saves an array of integers.
func void PM_SaveIntArray(var string name, var int ptr, var int elements)\n
Parameters var string name
Name of the field in saved archive var int ptr
Pointer to the array var int elements
Number of elements in array "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savestringarray","title":"PM_SaveStringArray
","text":"PM_SaveStringArray
Saves an array of integers.
func void PM_SaveStringArray(var string name, var int ptr, var int elements)\n
Parameters var string name
Name of the field in saved archive var int ptr
Pointer to the array var int elements
Number of elements in array "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#unarchiver","title":"Unarchiver","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_load","title":"PM_Load
","text":"PM_Load
Universal function to load integers, floats, class pointers and int arrays.
func int PM_Load(var string name)\n
Parameters var string name
Name of the loaded field Return value The function returns the data existing in the archive at the given field.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadint","title":"PM_LoadInt
","text":"PM_LoadInt
Returns an integer stored in the archive.
func int PM_LoadInt(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfloat","title":"PM_LoadFloat
","text":"PM_LoadFloat
Returns a daedalus float stored in the archive.
func int PM_LoadFloat(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadstring","title":"PM_LoadString
","text":"PM_LoadString
Returns a string stored in the archive.
func string PM_LoadString(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncid","title":"PM_LoadFuncID
","text":"PM_LoadFuncID
Returns a function ID stored in the archive.
func int PM_LoadFuncID(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncoffset","title":"PM_LoadFuncOffset
","text":"PM_LoadFuncOffset
Returns a function offset stored in the archive.
func int PM_LoadFuncOffset(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncptr","title":"PM_LoadFuncPtr
","text":"PM_LoadFuncPtr
Returns a function pointer stored in the archive.
func int PM_LoadFuncPtr(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadclassptr","title":"PM_LoadClassPtr
","text":"PM_LoadClassPtr
Returns a class pointer stored in the archive.
func int PM_LoadClassPtr(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadclass","title":"PM_LoadClass
","text":"PM_LoadClass
Loads a pointer to the class from the archive to destPtr
.
func void PM_LoadClass(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadarray","title":"PM_LoadArray
","text":"PM_LoadArray
Returns a pointer to array stored in the archive.
func int PM_LoadArray(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadarraytoptr","title":"PM_LoadArrayToPtr
","text":"PM_LoadArrayToPtr
Loads a pointer to array from the archive to destPtr
.
func void PM_LoadArrayToPtr(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadtoptr","title":"PM_LoadToPtr
","text":"PM_LoadToPtr
Universal function to load array or class pointer from the archive to destPtr
.
func void PM_LoadToPtr(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/queue/","title":"Queue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#queue","title":"Queue","text":"Info
Dependencies: - PermMem Implementation: Queue.d on GitHub
This package is an implementation of the Queue data structure and a queue for function calls.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#queue_1","title":"Queue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_create","title":"Q_Create
","text":"Q_Create
Creates a new queue and returns a handle to it.
func int Q_Create()\n
Return value The function returns a handle to a queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_enqueue","title":"Q_Enqueue
","text":"Q_Enqueue
Appends an integer to the back of the queue
func void Q_Enqueue(var int queue, var int value)\n
Parameters var int queue
Handle of a queue var int value
The value to be appended to the queue "},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_isempty","title":"Q_IsEmpty
","text":"Q_IsEmpty
Checks if the queue is empty.
func int Q_IsEmpty(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns TRUE
if the queue is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_advance","title":"Q_Advance
","text":"Q_Advance
Removes the oldest value from the queue and returns it.
func int Q_Advance(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns the oldest value in the queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_peek","title":"Q_Peek
","text":"Q_Peek
Returns the oldest value in the queue without removing it.
func int Q_Peek(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns the oldest value in the queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_for","title":"Q_For
","text":"Q_For
Function with the funcID
is called with every element of the list as parameter. The list element is passed to the function as a zCList
pointer.
func void Q_For(var int queue, var int funcID)\n
Parameters var int queue
Handle of a queue var int funcID
ID of function that is executed for all values in the queue (signature: void (zCList*)
) "},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_forf","title":"Q_ForF
","text":"Q_ForF
Like Q_For
, but with function as a parameter instead of a function ID.
func void Q_ForF(var int queue, var func f)\n
Parameters var int queue
Handle of a queue var func f
This function is executed for all values in the queue (signature: void (zCList*)
) "},{"location":"zengin/scripts/extenders/lego/tools/queue/#callbackqueue","title":"CallbackQueue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_create","title":"CQ_Create
","text":"CQ_Create
Creates a new callback queue and returns a handle to it.
func int CQ_Create()\n
Return value The function returns a handle to a callback queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueuenodata","title":"CQ_EnqueueNoData
","text":"CQ_EnqueueNoData
Appends a function to the callback queue.
func void CQ_EnqueueNoData(var int queue, var func function)\n
Parameters var int queue
Handle of a callback queue var func function
A function with no return value, expecting no parameter "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueuedata","title":"CQ_EnqueueData
","text":"CQ_EnqueueData
Appends a function together with a value to the callback queue.
func void CQ_EnqueueData(var int queue, var func function, var int data)\n
Parameters var int queue
Handle of a callback queue var func function
A function with no return value, expecting an integer as a parameter. var int data
When calling function
, this value is passed as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueue","title":"CQ_Enqueue
","text":"CQ_Enqueue
Appends a function together with an optional value to the callback queue. This function should not usually be used. Use CQ_EnqueueData
and CQ_EnqueueNoData
instead.
func void CQ_Enqueue(var int queue, var int funcID, var int data, var int hasData)\n
Parameters var int queue
Handle of a callback queue var int funcID
The function ID of a function to be appended to the callback queue. var int data
If hasData is not 0, this value is passed to the associated function. var int hasData
Must be 0 if the function does not expect an integer as a parameter, otherwise not 0. "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_isempty","title":"CQ_IsEmpty
","text":"CQ_IsEmpty
Checks if no function is in the callback queue.
func int CQ_IsEmpty(var int queue)\n
Parameters var int queue
Handle of a callback queue Return value
The function returns TRUE
if the callback queue is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_advance","title":"CQ_Advance
","text":"CQ_Advance
Executes the foremost function of the callback queue and removes it from the callback queue.
func void CQ_Advance(var int queue)\n
Parameters var int queue
Handle of a callback queue "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_exhaust","title":"CQ_Exhaust
","text":"CQ_Exhaust
Executes all functions contained in the callback queue.
func void CQ_Exhaust(var int queue)\n
Parameters var int queue
Handle of a callback queue "},{"location":"zengin/scripts/extenders/lego/tools/random/","title":"Random","text":""},{"location":"zengin/scripts/extenders/lego/tools/random/#random","title":"Random","text":"Info
Dependencies: - None Implementation: Random.d on GitHub
Provides more random randomization than Hlp_Random()
function.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#initialization","title":"Initialization","text":"Initialize with LeGo_Random
flag.
LeGo_Init(LeGo_Random);\n
"},{"location":"zengin/scripts/extenders/lego/tools/random/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/random/#r_next","title":"r_Next
","text":"r_Next
Returns a random number.
func int r_Next()\n
Return value The function returns a random number.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_max","title":"r_Max
","text":"r_Max
Returns a random number from 0 to max
.
func int r_Max(var int max)\n
Parameters var int max
Maximum value of number Return value
The function returns a random number from 0 to 'max'.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_minmax","title":"r_MinMax
","text":"r_MinMax
Returns a random number from 'min' to 'max'.
func int r_MinMax(var int min, var int max)\n
Parameters var int max
Maximum value of number var int min
Minimum value of number Return value
The function returns a random number from min
to max
.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_init","title":"r_Init
","text":"r_Init
Initializes the random number generator. Happens optionally in LeGo_Init
.
func void r_Init(var int seed)\n
Parameters var int seed
The initializing value "},{"location":"zengin/scripts/extenders/lego/tools/random/#r_defaultinit","title":"r_DefaultInit
","text":"r_DefaultInit
Initializes the random number generator based on the current time.
func void r_DefaultInit()\n
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/","title":"Sprite","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite","title":"Sprite","text":"Info
Dependencies: - PermMem Implementation: Sprite.d on GitHub
Sprite package implements functions for working with 2D sprites.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#initialization","title":"Initialization","text":"Initialize with LeGo_Sprite
flag.
LeGo_Init(LeGo_Sprite);\n
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_create","title":"Sprite_Create
","text":"Sprite_Create
Creates a sprite. The dimensions are in virtual coordinates.
func int Sprite_Create(var int x, var int y, var int width, var int height, var int color, var string tex)\n
Parameters var int x
X position of sprite (virtual) var int y
Y position of sprite (virtual) var int width
Width of sprite (virtual) var int height
Height of sprite (virtual) var int color
Color of sprite (in RGBA format) var string tex
Name of the sprite texture Return value
The function returns the handle of the created sprite.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_createpxl","title":"Sprite_CreatePxl
","text":"Sprite_CreatePxl
Creates a sprite. The dimensions are in pixels.
func int Sprite_CreatePxl(var int x, var int y, var int width, var int height, var int color, var string tex)\n
Parameters var int x
X position of sprite (pixels) var int y
Y position of sprite (pixels) var int width
Width of sprite (pixels) var int height
Height of sprite (pixels) var int color
Color of sprite (in RGBA format) var string tex
Name of the sprite texture Return value
The function returns the handle of the created sprite.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_render","title":"Sprite_Render
","text":"Sprite_Render
Renders a sprite on a screen (must be visible first).
func void Sprite_Render(var int h)\n
Parameters var int h
Handle of the sprite "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvisible","title":"Sprite_SetVisible
","text":"Sprite_SetVisible
Sets the visibility of a sprite.
func void Sprite_SetVisible(var int h, var int visible)\n
Parameters var int h
Handle of the sprite var int visible
Visibility flag (0 for invisible, 1 for visible) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setprio","title":"Sprite_SetPrio
","text":"Sprite_SetPrio
Sets the priority of a sprite. The higher the priority, the closer the sprite is to the camera.
func void Sprite_SetPrio(var int h, var int prio)\n
Parameters var int h
Handle of the sprite var int prio
Priority of the sprite "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_scale","title":"Sprite_Scale
","text":"Sprite_Scale
Scales a sprite.
func void Sprite_Scale(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X scale factor (as ikarus float) var int y
Y scale factor (as ikarus float) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setwidth","title":"Sprite_SetWidth
","text":"Sprite_SetWidth
Sets the width of a sprite in virtual coordinates.
func void Sprite_SetWidth(var int h, var int w)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setwidthpxl","title":"Sprite_SetWidthPxl
","text":"Sprite_SetWidthPxl
Sets the width of a sprite in pixels.
func void Sprite_SetWidthPxl(var int h, var int w)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setheight","title":"Sprite_SetHeight
","text":"Sprite_SetHeight
Sets the height of a sprite in virtual coordinates.
func void Sprite_SetHeight(var int h, var int hg)\n
Parameters var int h
Handle of the sprite var int hg
Height of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setheightpxl","title":"Sprite_SetHeightPxl
","text":"Sprite_SetHeightPxl
Sets the height of a sprite in pixels.
func void Sprite_SetHeightPxl(var int h, var int hg)\n
Parameters var int h
Handle of the sprite var int hg
Height of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setdim","title":"Sprite_SetDim
","text":"Sprite_SetDim
Sets the dimensions of a sprite in virtual coordinates.
func void Sprite_SetDim(var int h, var int w, var int hg)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in virtual coordinates var int hg
Height of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setdimpxl","title":"Sprite_SetDimPxl
","text":"Sprite_SetDimPxl
Sets the dimensions of a sprite in pixels.
func void Sprite_SetDimPxl(var int h, var int w, var int hg)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in pixels var int hg
Height of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpos","title":"Sprite_SetPos
","text":"Sprite_SetPos
Sets the position of a sprite in virtual coordinates.
func void Sprite_SetPos(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X position of the sprite (virtual) var int y
Y position of the sprite (virtual) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpospxl","title":"Sprite_SetPosPxl
","text":"Sprite_SetPosPxl
Sets the position of a sprite in pixels.
func void Sprite_SetPosPxl(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X position of the sprite (pixels) var int y
Y position of the sprite (pixels) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpospxlf","title":"Sprite_SetPosPxlF
","text":"Sprite_SetPosPxlF
Sets the position of a sprite in pixels (floating point).
func void Sprite_SetPosPxlF(var int h, var int xf, var int yf)\n
Parameters var int h
Handle of the sprite var int xf
X position of the sprite (pixels but as a float) var int yf
Y position of the sprite (pixels but as a float) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setcolor","title":"Sprite_SetColor
","text":"Sprite_SetColor
Sets the color of a sprite.
func void Sprite_SetColor(var int h, var int col)\n
Parameters var int h
Handle of the sprite var int col
Color of the sprite (in RGBA format) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvertcolor","title":"Sprite_SetVertColor
","text":"Sprite_SetVertColor
Sets the color of a vertex in a sprite.
func void Sprite_SetVertColor(var int h, var int vert, var int col)\n
Parameters var int h
Handle of the sprite var int vert
Index of the vertex (0-3) var int col
Color of the vertex (in RGBA format) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setuv","title":"Sprite_SetUV
","text":"Sprite_SetUV
Sets the UV coordinates of a sprite.
func void Sprite_SetUV(var int h, var int x0, var int y0, var int x1, var int y1)\n
Parameters var int h
Handle of the sprite var int x0
X coordinate of the top-left UV var int y0
Y coordinate of the top-left UV var int x1
X coordinate of the bottom-right UV var int y1
Y coordinate of the bottom-right UV "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvertuv","title":"Sprite_SetVertUV
","text":"Sprite_SetVertUV
Sets the UV coordinates of a vertex in a sprite.
func void Sprite_SetVertUV(var int h, var int vert, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int vert
Index of the vertex (0-3) var int x
X coordinate of the UV var int y
Y coordinate of the UV "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_rotate","title":"Sprite_Rotate
","text":"Sprite_Rotate
Rotates a sprite by a given angle in degrees.
func void Sprite_Rotate(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_rotater","title":"Sprite_RotateR
","text":"Sprite_RotateR
Rotates a sprite by a given angle in radians.
func void Sprite_RotateR(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in radians "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotation","title":"Sprite_SetRotation
","text":"Sprite_SetRotation
Sets the rotation of a sprite in degrees.
func void Sprite_SetRotation(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotationr","title":"Sprite_SetRotationR
","text":"Sprite_SetRotationR
Sets the rotation of a sprite in radians.
func void Sprite_SetRotationR(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in radians "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotationsc","title":"Sprite_SetRotationSC
","text":"Sprite_SetRotationSC
Sets the rotation of a sprite using sine and cosine values.
func void Sprite_SetRotationSC(var int h, var int sin, var int cos)\n
Parameters var int h
Handle of the sprite var int sin
Sine value of the rotation var int cos
Cosine value of the rotation "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#helper-functions","title":"Helper functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sincosapprox","title":"SinCosApprox
","text":"SinCosApprox
Approximates sine and cosine values for a given angle. Keeps them in var int sinApprox
var int cosApprox;
variables.
func void SinCosApprox(var int angle)\n
Parameters var int angle
Angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/","title":"StringBuilder","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#stringbuilder","title":"StringBuilder","text":"Info
Dependencies: - None Implementation: StringBuilder.d on GitHub
The StringBuilder is a package, designed to easily concatenate multiple elements into a string (without ConcatStrings
and IntToString
).
All created StringBuilders are transient. All functions starting from SB_InitBuffer
, including it, use the active StringBuilder set with SB_New
or SB_Use
, so there is no var int stringBuilder
parameter in functions. A look at the example explains what I mean.
Warning
The StringBuilder works with pointers, not handles like many other LeGo packages.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_new","title":"SB_New
","text":"SB_New
Creates and returns a new StringBuilder
. At the same time, this new StringBuilder
is set as active. (See SB_Use
.)
func int SB_New()\n
Return value The function returns a pointer to a new StringBuilder
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_use","title":"SB_Use
","text":"SB_Use
Marks this StringBuilder
as active. It can now be used with the functions.
func void SB_Use(var int sb)\n
Parameters var int sb
Pointer to a StringBuilder
, returned from SB_New
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_get","title":"SB_Get
","text":"SB_Get
Returns the active StringBuilder
.
func int SB_Get()\n
Return value The function returns the active StringBuilder
object - last set with SB_Use
or just created with SB_New
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_initbuffer","title":"SB_InitBuffer
","text":"SB_InitBuffer
If the size of the resulting string is already known, the buffer can be set manually. This is usually not necessary.
func void SB_InitBuffer(var int size)\n
Parameters var int size
Size in bytes. Warning! Only works if the StringBuilder
has been newly created! "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_clear","title":"SB_Clear
","text":"SB_Clear
Empties the current StringBuilder
. It is not destroyed in the process, so it can be used again. If the object has a buffer allocated, the buffer is freed.
func void SB_Clear()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_release","title":"SB_Release
","text":"SB_Release
Releases the current stream of the StringBuilder
. The StringBuilder
is destroyed, and the stream can be obtained via SB_GetStream
.
func void SB_Release()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_destroy","title":"SB_Destroy
","text":"SB_Destroy
Completely destroys the StringBuilder
.
func void SB_Destroy()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_tostring","title":"SB_ToString
","text":"SB_ToString
Returns a copy of the stream as a string.
func string SB_ToString()\n
Return value The function returns the copy of the active StringBuilder
as a string. If the StringBuilder
object doesn't have a buffer allocated, an empty string is returned.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_tostream","title":"SB_ToStream
","text":"SB_ToStream
Returns a copy of the stream in raw format.
func int SB_ToStream()\n
Return value The function returns a copy of the stream in raw format (char[]
)
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_getstream","title":"SB_GetStream
","text":"SB_GetStream
Doesn't copy the stream, but returns it as it is.
func int SB_GetStream()\n
Return value The function returns the stream as it is. SB_Destroy
or SB_Clear
destroy the returned pointer.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_length","title":"SB_Length
","text":"SB_Length
Returns the current length of the stream. Similar to STR_Len
from Ikarus .
func int SB_Length()\n
Return value The function returns the current length of the active StringBuilder
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_setlength","title":"SB_SetLength
","text":"SB_SetLength
Sets the length of the stream. When increasing, zero bytes are appended.
func void SB_SetLength(var int length)\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#stream-operations","title":"Stream operations","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb","title":"SB
","text":"SB
Appends a string, to the active StringBuilder
.
func void SB(var string s)\n
Parameters var string s
The appended string "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbi","title":"SBi
","text":"SBi
Appends an integer in text form, to the active StringBuilder
.
func void SBi(var int i)\n
Parameters var int i
The appended integer "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbc","title":"SBc
","text":"SBc
Appends a byte, to the active StringBuilder
. (e.g. 82 for 'R' - An ASCII table can be quickly found)
func void SBc(var int c)\n
Parameters var int c
The appended byte (ASCII table character) "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbraw","title":"SBraw
","text":"SBraw
Appends a raw bytes array, to the active StringBuilder
.
func void SBraw(var int ptr, var int len)\n
Parameters var int ptr
Pointer to the appended array var int len
Length of an array "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbflt","title":"SBflt
","text":"SBflt
Appends a Daedalus float in text form, to the active StringBuilder
.
func void SBflt(var float x)\n
Parameters var float x
The appended Daedalus float value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbf","title":"SBf
","text":"SBf
Appends an Ikarus float in text form, to the active StringBuilder
.
func void SBf(var int x)\n
Parameters var float x
The appended Ikarus float value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbw","title":"SBw
","text":"SBw
Appends a 4-byte raw data (interpreted as an integer x
), to the active StringBuilder
.
func void SBw(var int x)\n
Parameters var int i
The appended value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#independent-functions","title":"Independent Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_escape","title":"STR_Escape
","text":"STR_Escape
Makes escape sequences out of non-writable characters. For example, newline character \\n
becomes \\\\n
, tab character \\t
becomes \\\\t
, etc.
func string STR_Escape(var string s0)\n
Parameters var string s0
The string to be added escape sequences Return value
The function returns a new string with escape sequences added for special characters.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_unescape","title":"STR_Unescape
","text":"STR_Unescape
Counterpart to STR_Escape
. Escape sequences like \\n
, \\r
or \\t
are converted back.
func string STR_Unescape(var string s0)\n
Parameters var string s0
The string to be removed escape sequences Return value
The function returns a new string with escape sequences replaced by their corresponding characters.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_startswith","title":"STR_StartsWith
","text":"STR_StartsWith
Checks if the input string s
starts with the specified prefix string.
func int STR_StartsWith(var string str, var string start) \n
Parameters var string str
The string to be checked var string start
The searched prefix Return value
The function returns TRUE
if the string starts with the prefix, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#additional-functions","title":"Additional Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#buildstringsymbolsarray","title":"BuildStringSymbolsArray
","text":"BuildStringSymbolsArray
Creates an array of all string symbols found in the parser's string table.
func int BuildStringSymbolsArray()\n
Return value The function returns created array.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#getstringsymbolbyaddr","title":"GetStringSymbolByAddr
","text":"GetStringSymbolByAddr
Retrieves the symbol at the specified address from the string table.
func int BuildStringSymbolsArray()\n
Return value The function returns a parser symbol at the given address.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#basic-functionality","title":"Basic functionality","text":"This is how function that builds a string looks without StringBuilder
:
func void PrintMyNumbers(var int x0, var int x1, var int x2) {\n var string res;\n res = ConcatStrings(IntToString(x0), \", \");\n res = ConcatStrings(res, IntToString(x1));\n res = ConcatStrings(res, \", \");\n res = ConcatStrings(res, IntToString(x2));\n PrintS(res);\n};\n
And now the function that uses StringBulider
: func void PrintMyNumbers(var int x0, var int x1, var int x2) {\n var int s; s = SB_New(); // Create StringBuilder\n SBi(x0); // Append Int\n SB (\", \"); // Append string\n SBi(x1); // Append Int\n SB (\", \"); // Append string\n SBi(x2); // Append Int\n PrintS(SB_ToString()); // Get output as a string\n SB_Destroy(); // Destroy StringBuilder\n};\n
Looks much more pleasant, right? But why do we create a StringBuilder and then not use it? The idea is the following: A StringBuilder is created with SB_New()
and set as the active StringBuilder in the background. The package only supports one StringBuilder at a time, which will keep the pointer in case we want to use another StringBuilder in between."},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#multiple-stringbuilders","title":"Multiple StringBuilders","text":"Simple example. We want to fill two StringBuilders at the same time and then return them combined:
func string Example2() {\n // Create two StringBuilders:\n var int s0; s0 = SB_New();\n var int s1; s1 = SB_New();\n\n // Set the first StringBuilder as active and fill it.\n SB_Use(s0);\n SB(\"Hello \");\n SB(\"World!\");\n\n // Set the second StringBuilder as active and fill it.\n SB_Use(s1);\n SB(\"This is \");\n SB(\"the hero speaking!\");\n\n // Now we want to combine the two StringBuilders.\n // The system doesn't actually provide for such an operation, but it can still be done using a helper string\n var string str; str = SB_ToString(); // This string now says \u201cThis is the hero speaking!\u201d\n\n SB_Use(s0);\n SB(\" \");\n SB(str);\n\n str = SB_ToString(); // Now \"Hello world! This is the hero speaking!\" are in the string.\n\n // The rest is already known, we destroy StringBuilders\n SB_Destroy();\n SB_Use(s1);\n SB_Destroy();\n\n return str;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/talents/","title":"Talents","text":""},{"location":"zengin/scripts/extenders/lego/tools/talents/#talents","title":"Talents","text":"Info
Dependencies: - PermMem Implementation: Talents.d on GitHub
The Talents package does two things:
save any number of values for a specific NPC (effectively AIVar array extension). identify NPC by unique ID. Talents package uses one free AIVar variables, the default is AIVar with the index 89 that can be customized in Userconst.d
the AIV_TALENT
constant.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/talents/#npc_getid","title":"Npc_GetID
","text":"Npc_GetID
Returns unique ID specific for provided NPC.
func int Npc_GetID(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get ID Return value
The function returns NPCs unique ID.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#npc_findbyid","title":"Npc_FindByID
","text":"Npc_FindByID
Finds the NPC pointer of an NPC with the given ID.
func int Npc_FindByID(var int ID)\n
Parameters Return value
The function returns NPC pointer.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_createtalent","title":"TAL_CreateTalent
","text":"TAL_CreateTalent
Creates a talent into which you can later save a value for every NPC (just like AI_Var
).
func int TAL_CreateTalent()\n
Return value The function returns value that can be later used as a talent ID.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_setvalue","title":"TAL_SetValue
","text":"TAL_SetValue
Sets a new value to the specified talent.
func void TAL_SetValue(var C_NPC npc, var int talent, var int value)\n
Parameters var C_NPC npc
Set the talent value for this NPC var int talent
Talent ID var int value
Value to be set "},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_getvalue","title":"TAL_GetValue
","text":"TAL_GetValue
Returns the value of a saved talent for specified NPC.
func int TAL_GetValue(var C_NPC npc, var int talent)\n
Parameters var C_NPC npc
Get the talent value from this NPC var int talent
Talent ID "},{"location":"zengin/scripts/extenders/lego/tools/timer/","title":"Timer","text":""},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer","title":"Timer","text":"Info
Dependencies: - None Implementation: Timer.d on GitHub
Timer is a better alternative to the timers that Gothic offers. The FrameFunctions and Anim8 packages are already based on it. It isn't possible to modify the current time, as this would only cause difficulties.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#initialization","title":"Initialization","text":"Initialize with LeGo_Timer
flag.
LeGo_Init(LeGo_Timer);\n
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_1","title":"Timer
","text":"Timer
Returns the current playing time. If a new game is started, the time is 0. It is measured in milliseconds.
func int Timer()\n
Return value The function returns current playing time in milliseconds.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timergt","title":"TimerGT
","text":"TimerGT
Returns the current game time, but the timer is paused when the game is paused (in the menu or status screen).
func int TimerGT()\n
Return value The function returns current playing time in milliseconds, but without measuring time when game is paused.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timerf","title":"TimerF
","text":"TimerF
Alias to Timer
function that returns the time as an Ikarus float value.
func int TimerF()\n
Return value The function returns current playing time as an Ikarus float value.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_setpause","title":"Timer_SetPause
","text":"Timer_SetPause
Pauses the timer (and thus all FrameFunctions and running animations).
func void Timer_SetPause(var int on)\n
Parameters "},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_setpauseinmenu","title":"Timer_SetPauseInMenu
","text":"Timer_SetPauseInMenu
The timer can automatically pause when the game is paused. (status screen, main menu...)
func void Timer_SetPauseInMenu(var int on)\n
Parameters var int on
Automatic pause on/off "},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_ispaused","title":"Timer_IsPaused
","text":"Timer_IsPaused
This can be used to query whether the timer is paused.
func int Timer_IsPaused()\n
Return value The function returns TRUE
if the timer is paused, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/view/","title":"View","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#view","title":"View","text":"Info
Dependencies: - PermMem - Interface Implementation: View.d on GitHub
This package can create textures on the screen and work with them in an extended manner.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#initialization","title":"Initialization","text":"Initialize with LeGo_View
flag.
LeGo_Init(LeGo_View);\n
"},{"location":"zengin/scripts/extenders/lego/tools/view/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#view_create","title":"View_Create
","text":"View_Create
Creates a zCView
with virtual coordinates.
func int View_Create(var int x1, var int y1, var int x2, var int y2) \n
Parameters var int x1
/var int y1
Top-left corner coordinates (virtual) var int x2
/var int y2
Bottom-right corner coordinates (virtual) Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createpxl","title":"View_CreatePxl
","text":"View_CreatePxl
Alias for View_Create
using pixel coordinates.
func int View_CreatePxl(var int x1, var int y1, var int x2, var int y2) \n
Parameters var int x1
/var int y1
Top-left corner coordinates (pixel) var int x2
/var int y2
Bottom-right corner coordinates (pixel) Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createcenter","title":"View_CreateCenter
","text":"View_CreateCenter
Creates a zCView
with virtual coordinates centered.
func int View_CreateCenter(var int x, var int y, var int width, var int height)\n
Parameters var int x
Horizontal position var int y
Vertical position var int width
Width of the view var int height
Height of the view Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createcenterpxl","title":"View_CreateCenterPxl
","text":"View_CreateCenterPxl
Alias for View_CreateCenter
using pixel coordinates.
func int View_CreateCenterPxl(var int x, var int y, var int width, var int height)\n
Parameters var int x
Horizontal position var int y
Vertical position var int width
Width of the view var int height
Height of the view Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_get","title":"View_Get
","text":"View_Get
Alias for get
form PermMem.
zCView View_Get(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_getptr","title":"View_GetPtr
","text":"View_GetPtr
Alias for getPtr
form PermMem.
func int View_GetPtr(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_render","title":"View_Render
","text":"View_Render
Renders a zCView
. Should be used sparingly, as it works only in specific cases.
func void View_Render(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_settexture","title":"View_SetTexture
","text":"View_SetTexture
Assigns a texture to a view. The key function of this package.
func void View_SetTexture(var int hndl, var string texture)\n
Parameters var int hndl
Handle created with View_Create
var string texture
Filename of a texture "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_gettexture","title":"View_GetTexture
","text":"View_GetTexture
Gets the name of a previously assigned texture.
func string View_GetTexture(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
Return value
The function returns the previously assigned texture.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_setcolor","title":"View_SetColor
","text":"View_SetColor
Sets the color of a view.
func void View_SetColor(var int hndl, var int color)\n
Parameters var int hndl
Handle created with View_Create
var int color
zColor, can be created with RGBA "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_getcolor","title":"View_GetColor
","text":"View_GetColor
Gets the color of a view.
func int View_GetColor(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
Return value
The function returns the full zColor.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_open","title":"View_Open
","text":"View_Open
Opens a view. It will be displayed on the screen.
func void View_Open(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_close","title":"View_Close
","text":"View_Close
Closes a view. It disappears from the screen but can still be used.
func void View_Close(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_delete","title":"View_Delete
","text":"View_Delete
Alias for delete
.
`zCView` View_Delete(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_resize","title":"View_Resize
","text":"View_Resize
Scales a view to a virtual size. The top-left position of the view remains fixed.
func void View_Resize(var int hndl, var int width, var int height)\n
Parameters var int hndl
Handle created with View_Create
var int width
New width of the view var int height
New height of the view "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_resizepxl","title":"View_ResizePxl
","text":"View_ResizePxl
Alias for View_Resize
using pixel coordinates.
func void View_ResizePxl(var int hndl, var int width, var int height)\n
Parameters var int hndl
Handle created with View_Create
var int width
New width of the view var int height
New height of the view "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_move","title":"View_Move
","text":"View_Move
Moves the view by virtual units.
func void View_Move(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
Shift left/right var int y
Shift up/down "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_movepxl","title":"View_MovePxl
","text":"View_MovePxl
Alias for View_Move
using pixel coordinates.
func void View_MovePxl(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
Shift left/right var int y
Shift up/down "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_moveto","title":"View_MoveTo
","text":"View_MoveTo
Moves the top-left corner of the view to a virtual position.
func void View_MoveTo(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
New horizontal position (-1 for no change) var int y
New vertical position (-1 for no change) "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_movetopxl","title":"View_MoveToPxl
","text":"View_MoveToPxl
Alias for View_MoveTo
using pixel coordinates.
func void View_MoveToPxl(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
New horizontal position (-1 for no change) var int y
New vertical position (-1 for no change) "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_addtext","title":"View_AddText
","text":"View_AddText
Adds a text line to the view. The position is virtual and relative to the view's position. If the view is moved, the text moves as well.
func void View_AddText(var int hndl, var int x, var int y, var string text, var string font)\n
Parameters var int hndl
Handle created with View_Create
var int x
Horizontal position var int y
Vertical position var string text
Added text var string font
Used Font "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_deletetext","title":"View_DeleteText
","text":"View_DeleteText
Removes all text added with View_AddText
.
func void View_DeleteText(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_top","title":"View_Top
","text":"View_Top
Places the view above all others.
func void View_Top(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#display-a-texture-on-the-screen","title":"Display a texture on the screen","text":"Here a texture should be displayed over the entire screen:
func void Example1() {\n var int View; \n View = View_Create(0, 0, PS_VMax, PS_VMax); // Virtual coordinates\n View_SetTexture(View, \"MyTexture.tga\"); // Assign a texture to the view\n // display the view on the screen:\n View_Open(View);\n};\n
This would mean that the texture would be permanently visible on the screen (even after loading/saving/restarting). If we want it to disappear we have to use either View_Delete
or View_Close
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#display-a-texture-with-pixel-coordinates","title":"Display a texture with pixel coordinates","text":"Now a texture should be displayed at the top right and be 256 x 256 pixels in size:
func void Example2() {\n Print_GetScreenSize();\n var int View;\n View = View_CreatePxl(Print_Screen[PS_X] - 256, 0, Print_Screen[PS_X], 256); // Pixel coordinates\n View_SetTexture(View, \"MYTEXTURE.TGA\");\n View_Open(View);\n};\n
To get the size of the screen we use the interface package.
"},{"location":"zengin/scripts/extenders/standalone/","title":"Standalone Scripts","text":""},{"location":"zengin/scripts/extenders/standalone/#standalone-scripts","title":"Standalone Scripts","text":"Over the years Gothic modders have created many useful features to use with Zengin scripts. This section contains documentation for some scripts that are \"standalone\", meaning they are not part of larger packages, but are often small features to make modders lives easier.
"},{"location":"zengin/scripts/extenders/standalone/#script-bins","title":"Script Bins","text":"A few people came up with the idea of collecting scripts scattered on the forums, which resulted in the so-called Script Bins.
Warning
Script bins aren't updated frequently, so for the latest updates and new scripts also check the ScriptBin WoG thread.
"},{"location":"zengin/scripts/extenders/standalone/#wog-script-bin","title":"WoG Script Bin","text":"Script bin made by Kirides containing scripts from German WoG forum.
https://apps.kirides.de/wog-script-bin/
"},{"location":"zengin/scripts/extenders/standalone/#scriptbin-github-repository","title":"ScriptBin GitHub repository","text":"Lehona has created a GitHub repository that contains scripts from some of the modders.
https://github.com/Lehona/ScriptBin
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/","title":"gameKeyEvents","text":""},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#gamekeyevents","title":"gameKeyEvents","text":"Quick overview
Author: mud-freak Platform: G1, G2NotR Category: Engine, Keys
gameKeyEvents.d is a script, which handles key events with the oCGame::HandleEvent
hook. Better alternative for FrameFunction
with MEM_KeyState
with which you don't have to check whether any menu is opened or player is in dialogue or can move etc.
Author's description I looked up the address within oCGame::HandleEvent
. I made it into a universally usable script for Gothic 1 and Gothic 2.
One could argue now that this is not much different from a FrameFunction
with MEM_KeyState
. The difference is that this approach saves the extra work of checking if any menu is open, whether the player is in a dialog, whether the player may move, etc. Also this function is \"event driven\", meaning it is really only called when a key is pressed/held instead of every frame in vain. So it's arguably more performant.
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#dependencies","title":"Dependencies","text":""},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#initialization","title":"Initialization","text":"Call Game_KeyEventInit()
in the Init_Global()
or other initialization function.
Game_KeyEventInit();\n
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#implementation","title":"Implementation","text":" gameKeyEvents.d on WoG forum
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#usage","title":"Usage","text":"To add a key pressing detection edit the main function Game_KeyEvent
.
func int Game_KeyEvent(var int key, var int pressed) {\n if (key == KEY_LBRACKET) && (pressed) {\n // Here enter your code.\n return TRUE;\n };\n return FALSE;\n};\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/","title":"setBarPositions","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#setbarpositions","title":"setBarPositions","text":"Quick overview
Author: mud-freak Platform: G1, G2NotR Category: Engine, Interface
setBarPositions.d is a script that allows changing position of original gothic bars (HP, Mana, Swim, focus). Changes are directly in the engine, so bars are normally scaled.
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#dependencies","title":"Dependencies","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#initialization","title":"Initialization","text":"Call it in the Init_Global()
or other initialization function. Set the manaAlwaysOn
and swimAlwaysOn
to TRUE/FALSE.
SetBarPositions_Init(manaAlwaysOn, swimAlwaysOn);\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#implementation","title":"Implementation","text":" setBarPositions.d on WoG forum
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#usage","title":"Usage","text":"To change positions of bars edit the main function SetBarPosition
. Look at the examples to see how you can adjust it to your preferences.
func int SetBarPosition(var int barPtr) {\n var oCViewStatusBar bar; bar = _^(barPtr);\n var int x; var int y;\n\n if (barPtr == MEM_Game.hpBar) {\n // Original\n x = Print_ToVirtual(10, PS_X); // 10 px from the left\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.manaBar) {\n // Original\n x = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizex, PS_X); // 10 px from the right\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.swimBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.focusBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = Print_ToVirtual(10, PS_Y); // 10 px from the top\n };\n\n return x | (y << 14);\n};\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#all-bars-on-the-left-side","title":"All bars on the left side","text":"/*\n * EXAMPLE: Stacked on the left\n */\nfunc int SetBarPosition(var int barPtr) {\n var oCViewStatusBar bar; bar = _^(barPtr);\n var int x; var int y;\n\n if (barPtr == MEM_Game.hpBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 3 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.manaBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 2 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.swimBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 1 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.focusBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = Print_ToVirtual(10, PS_Y); // 10 px from the top\n };\n\n return x | (y << 14);\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/","title":"zParserExtender","text":""},{"location":"zengin/scripts/extenders/zparserextender/#zparserextender","title":"zParserExtender","text":"zParserExtender extends ZenGin's parser and adds many useful features. It significantly extends the functionality of scripts with added functionality and new external functions. It also enhances script compilation, allowing to compile OU files directly with the game and allowing for runtime script injection. Since the Union version 1.0m
zParserExtender is fully integrated in Union itself.
Note
This is mostly a translation of the original release post
Contacts Author Gratt GitHub zParserExtender Forum zParserExtender"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/","title":"Trigger functions and the `C_Trigger` class","text":""},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#trigger-functions-and-the-c_trigger-class","title":"Trigger functions and the C_Trigger
class","text":"zParserExtender also implements cyclical functions called triggers - not to be confused with triggers in ZEN files, similar to a part of the functionality implemented in LeGo AI_Functions. These functions are called independently after a specified period of time. These triggers can also store user information. Up to 16 int variables can be stored in each trigger as well as self
, other
and victim
instances.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#class-definition","title":"Class definition","text":"To define a trigger, the C_Trigger
class is used:
/// Union zParserExtender Trigger class\nclass C_Trigger\n{\n var int Delay; // defines the frequency (in milliseconds) at which the function will be called.\n var int Enabled; // determines if the trigger is active. If the value is equal to zero, the trigger is destroyed.\n var int AIVariables[16]; // user data, which can be set independently when creating trigger (yes, you can write there absolutely everything you want).\n\n // Hidden variable members\n /*\n - Func - The function that the trigger will call.\n - Self - The NPC that will be placed in `self` when the function is called.\n - Other - An NPC that will be placed in `other` when the function is called.\n - Victim - The NPC that will be placed in `victim` when the function is called.\n */\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#creating-instances","title":"Creating instances","text":"There are two external functions that are used to create C_Trigger
instance.
// function returns a trigger with no NPC (self, other or victim) bound to it\nfunc C_Trigger AI_StartTriggerScript( var string funcName,\n var int delay) {};\n\n// function is extended, if certain participants need to be assigned to it\nfunc C_Trigger AI_StartTriggerScriptEx( var string funcName,\n var int delay,\n var C_Npc slf,\n var C_Npc oth,\n var C_Npc vct) {};\n
Both of these functions return an instance of C_Trigger
instance. You can of course configure the instance after its creation. You can, for example, fill in the AIVariables
with relevant data. The trigger function has the required signature if 'func int f()'. It must return a value indicating the state of the loop. If the function returns LOOP_END
the trigger will be stopped and the instance deleted. If LOOP_CONTINUE
is returned, the function will be called again after Delay
ms have passed.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#poison-example","title":"Poison example","text":"// Implement a trigger to simulate the effect of poison debuff:\n// Let's create a trigger on function `c_loop` with a call interval of 1 second.\n// When the function is called, the instance hero will be placed in self (although it can be any other NPC if desired).\n// The rest of the instances are left null (not used).\n\nvar C_Trigger trigger;\ntrigger = AI_StartTriggerScriptEx(\"c_loop\", 1000, hero, null, null);\ntrigger.AIVariables[0] = 15; // how many times the function should be called\ntrigger.AIVariables[1] = 5; // how much damage to deal each iteration\n
The trigger function
func int c_loop()\n{\n // Create a loop end check, if the number of\n // available iterations has reached 0. If it did\n // we stop the trigger by returning the LOOP_END value.\n if (SelfTrigger.AIVariables[0] <= 0)\n {\n return Loop_end;\n };\n\n SelfTrigger.Delay -= 20; // Accelerate loop each call by 20 ms\n SelfTrigger.AIVariables[0] -= 1; // Reduce number of remaining repeats\n self.Attribute[ATR_HITPOINTS] -= SelfTrigger.AIVariables[1]; // Take health from self\n return LOOP_CONTINUE;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#trigger-scope","title":"Trigger scope","text":"Triggers can be divided into two types:
Global trigger ( AI_StartTriggerScript ) trigger created using this function works in all worlds. A trigger is considered global by default if neither self
nor other
nor victim
has been provided for it. Local trigger ( AI_StartTriggerScriptEx) trigger created with this function only works in the world in which it was created. A trigger is considered local if it has been presented with at least one NPC in self
, other
or victim
(not null). If you want to create a trigger without linking it to any NPC, it is recommended to simply pass hero as self
to the trigger. "},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#saving","title":"Saving","text":"The plugin creates a new save archive to save the information of the triggers that does not conflict with any of the built-in save files.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#searching","title":"Searching","text":"To search for a specific trigger, for example by NPC, the trigger external functions can be used.
// This way you can disable all triggers running on the `hero` instance\nvar C_Trigger trigger = FirstTrigger;\nvar C_Trigger trigger_saved;\nwhile (!Hlp_IsNULL(trigger))\n{\n trigger_saved = trigger;\n trigger = AI_GetNextTriggerBySelf(hero);\n trigger_saved.Enabled = false;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/","title":"Engine classes","text":""},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#engine-classes","title":"Engine classes","text":"zParserExtender implements various proxy classes that can be used to access game world objects.
Warning
It is not recommended to implement complex mechanics using these classes and functions. They are present as a simple backup option for accessing game world objects and for quick fixes.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_vob","title":"C_VOB","text":"This class represents basic pointer to a game world object.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_color","title":"C_Color","text":"Represents color in the RGBA format
class C_Color\n{\n var int R; // red channel value\n var int G; // green channel value\n var int B; // blue channel value\n var int A; // alpha channel value\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#zvec3","title":"zVEC3","text":"Represents 3D position in the world (float version for internal functions)
class zVEC3\n{\n var float X; // X coordinate\n var float Y; // Y coordinate\n var float Z; // Z coordinate\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_position","title":"C_Position","text":"Represents 3D position in the world
class C_Position\n{\n var int X; // X coordinate\n var int Y; // Y coordinate\n var int Z; // Z coordinate\n};\n
Externals: /// Returns the current position of the object in the world\n/// \n/// @param vob vob to ge the position of\n/// @return C_Position instance - position of the VOB\nfunc C_Position Vob_GetVobPosition( var C_Vob vob ) {};\n\n/// Sets the current position of the object in the world\n/// \n/// @param vob vob to get the position of\n/// @param pos new position of the vob\nfunc void Vob_SetVobPosition( var C_Vob vob, var C_Position pos ) {};\n
Note
The following classes define properties of C_VOB
objects or classes derived from it.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_vob_data","title":"C_VOB_DATA","text":"Represents universal zCVob
class
class C_VOB_DATA\n{\n var string Name; // object name\n var float VisualAlpha; // object's transparency 0.0 - 1.0\n var int ShowVisual; // display the mode\n var int DrawBBox3D; // show objects bounding box\n var int VisualAlphaEnabled; // enables objects transparency\n var int PhysicsEnabled; // enables object's physics\n var int IgnoredByTraceRay; // allow any object collisions\n var int CollDetectionStatic; // allow collision with static world polygons\n var int CollDetectionDynamic; // allow collision with dynamic world objects\n var int CastDynShadow; // display shadow of the object\n var int LightColorStatDirty; // allow static lighting of the object\n var int LightColorDynDirty; // allow dynamic lighting of the object\n var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only)\n var int DontWriteIntoArchive; // turns of the serialization of this object to the save file \n};\n
Externals: /// Returns the universal data of the zCVob object\n///\n/// @param vob VOB to get the position of\n/// @return general vob data C_Vob_Data\nfunc C_Vob_Data Vob_GetVobData( var C_Vob vob ) {};\n\n/// Sets the universal data to a zCVob object\n///\n/// @param vob VOB to get the position of\n/// @param data general vob data C_Vob_Data\nfunc void Vob_SetVobData( var C_Vob vob, var C_Vob_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_light_data","title":"C_LIGHT_DATA","text":"Represents zCVobLight
objects
class C_LIGHT_DATA\n{\n var int R; // red light intensity\n var int G; // green light intensity\n var int B; // blue light intensity\n var int Range; // radius\n var int RangeInv; // \n var int RangeBackup; // \n var int RangeAniActFrame; // current light animation frame for the radius\n var int RangeAniFPS; // speed of light animation for the radius\n var int ColorAniActFrame; // current light animation frame for colour\n var int ColorAniFPS; // speed of light animation for colour\n var int SpotConeAngleDeg; // angle of cone light source\n var int IsStatic; // whether the source is static\n var int RangeAniSmooth; // [UNUSED]\n var int RangeAniLoop; // [UNUSED]\n var int ColorAniSmooth; // allows soft transitions between colours\n var int ColorAniLoop; // [UNUSED]\n var int IsTurnedOn; // whether the light source is on\n var int LightQuality; // source quality (when statically compiling light) (0 - high, 1 - medium, 2 - low)\n var int LightType; // type of source (at static light compilation) (0 - point, 1 - cone)\n};\n
Externals: /// Returns zCVobLight object data\n///\n/// @param vobLight vobLight object\n/// @return C_Light_Data of the light\nfunc C_Light_Data Vob_GetLightData( var C_Vob vobLight ) {};\n\n/// Sets the data of a zCVobLight object\n///\n/// @param vobLight object to apply the light data to\n/// @param data C_Light_Data light data to be set\nfunc void Vob_SetLightData( var C_Vob vobLight, var C_Light_Data data ) {};\n\n/// Clears the list of animation colours for the light source\n///\n/// @param vobLight light vob\nfunc void Vob_ClearLightAniList( var C_Vob vobLight ) {};\n\n/// Adds a color to the colour list\n///\n/// @param vobLight object to apply the colour to\n/// @param col colour to be applied\nfunc void Vob_AddLightAniColor( var C_Vob vobLight, var C_Color col ) {};\n\n/// Adds a color to the colour list\n///\n/// @param vobLight object to apply the colour to\n/// @param r red colour channel\n/// @param g green colour channel \n/// @param b blue colour channel\nfunc void Vob_AddLightAniColorRGB( var C_Vob vobLight,\n var int r,\n var int g,\n var int b ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_mob_data","title":"C_MOB_DATA","text":"Represents data for the used oCMOB object
class C_MOB_DATA\n{\n var string VisibleName; // name shown above the object\n var int Hitpoints; // number of hitpoints\n var int Damage; // damage the object can cause\n var int IsDestroyed; // if the object is destroyed\n var int Moveable; // whether the object can be moved\n var int Takeable; // whether the object can be taken\n var int FocusOverride; // if the object will redefine focus in combat mode\n var int SndMat; // object's material (0 - wood, 1 - stone, 2 - metal, 3 - skin, 4 - clay, 5 - glass)\n var string VisualDestroyed; // model when the object is destroyed\n var string OwnerStr; // name of the instance of the owner of the object\n var string OwnerGuildStr; // name of the guild of the object\n var int Owner; // instance of the owner\n var int OwnerGuild; // guild instance\n var int FocusNameIndex; // the script string of the displayed name\n};\n
/// Returns the data of the oCMOB object\n///\n/// @param mob oCMOB object\n/// @return mob data\nfunc C_Mob_Data Vob_GetMobData( var C_Vob mob ) {};\n\n/// Sets the data of the oCMOB object\n///\n/// @param mob oCMOB object\n/// @param data C_Mob_Data to be set \nfunc void Vob_SetMobData( var C_Vob mob, var C_Mob_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_mobinter_data","title":"C_MOBINTER_DATA","text":"Represents data for the interactive object oCMobInter
class C_MOBINTER_DATA\n{\n var string TriggerTarget; // object name which will be triggered by OnTrigger\n var string UseWithItem; // name of the object instance that is needed for interaction\n var string Sceme; // name of the scene that corresponds to the object and character animations\n var string ConditionFunc; // scripting condition under which the interaction can be performed\n var string OnStateFuncName; // the name pattern of the functions that will be called when the object changes the state\n var int State; // the current state of the object\n var int State_num; // number of object's states\n var int State_target // current state of the object\n var int Rewind; // prohibits object updating\n var int MobStateAni; // current animation of the object\n var int NpcStateAni; // current character animation\n};\n
/// Returns the data of the oCMobInter object\n///\n/// @param mobInter oCMobInter object\n/// @return MobInter_Data of the object\nfunc MobInter_Data Vob_GetMobInterData( var C_Vob mobInter ) {};\n\n/// Sets the data of the oCMobInter object\n///\n/// @param mobInter oCMobInter object\n/// @param data MobInter_Data of the object\nfunc void Vob_SetMobInterData( var C_Vob mobInter, var C_MobInter_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_moblockable_data","title":"C_MOBLOCKABLE_DATA","text":"Represents data for the locked interactive object oCMobLockable
class C_MOBLOCKABLE_DATA\n{\n var int Locked; // whether the object is locked\n var int AutoOpen; // [UNUSED]\n var int PickLockNr; // current rotation number \n var string KeyInstance; // key instance name for the object\n var string PickLockStr; // combination to open the object (\"LRRLR\")\n};\n
/// Returns the data of the oCMobLockable object\n///\n/// @param mobLock oCMobLockable object\n/// @param data MobInter_Data of the object\nfunc C_MobLockable_Data Vob_GetMobInterData( var C_Vob mobLock ) {};\n\n/// Sets the data of the oCMobLockable object\n///\n/// @param mobLock oCMobLockable object\n/// @param data C_MobLockable_Data of the object\nfunc void Vob_SetMobInterData( var C_Vob mobLock, var C_MobLockable_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/","title":"Daedalus Injection","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/#daedalus-injection","title":"Daedalus Injection","text":"Script injection is a process of injecting Daedalus scripts on runtime without the need to recompile the scripts. This is essential for Union plugins that need to alter the scripts in a certain way, either for hotfixes or just for testing scripts without the need to recompile the whole .dat
file.
To inject a script, simply put a .d
or .src
file in Gothic/System/Autorun
directory and run the game.
Tip
Automatic injection does not extend to nested directories in the Autorun directory directly, but you can put a .src
file into Autorun
directory and the rest into a subdirectory to keep a cleaner structure.
Scripts in subdirectories can be accessed in two ways
They are specified in a .src
file The script file is an API script "},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/#api-script","title":"API script","text":"API scripts are .d
files placed in Autorun
subdirectories and are used as a dependency. It is assumed that the API script is not called on its own (or from a .src
) file, but is called using the dependency keyword After
in one of the injected script files' META block.
These scripts are meant to contain ready-made solution that need to be used by many other scripts as a dependency.
Warning
If the file specified in the After
tag in the META block does not exist, the current file will not be parsed and injected since the dependency is missing, and it would fail. Due to this it is best to ship the dependency in the Autorun directory even if it comes from a different plugin.
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/","title":"Hooking Daedalus","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#hooking-daedalus","title":"Hooking Daedalus","text":"Daedalus hooking is one of the most powerful features of this plugin. Hooking is a mechanism that allows you to replace any scripted object with a new one. To do this, you must define a new object with the same type, name and in the same namespace.
Hook/replacement will be performed only if the MergeMode
setting is set to true for the current script in the META block or in the parameter of the same name in the .ini
file of the mod.
Warning
If you forget to turn on the MergeMode
, the compilation will fail with the redefinition error.
When an object (instance, function or variable) is hooked/replaced, the original one is available under the same name with the _old
suffix (PC_Hero
-> PC_Hero_old
). This allows you to refer to the old object.
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#function-hook-example","title":"Function hook example","text":"func void ZS_Attack_Loop()\n{\n // if the enemy is a player and has no weapon, then\n // also sheath the weapon.\n if (Npc_IsPlayer(other) && !Npc_HasReadiedWeapon(other))\n {\n return LOOP_END;\n };\n\n // otherwise call the original function\n return ZS_Attack_Loop_Old();\n};\n
This kind of substitution works for instances and variables too.
Warning
While hooking an instances, you have to take care not to call the prototype. Prototype should be always changed back to the original class.
This is wronginstance pc_hero(Npc_Default)\n{\n pc_hero_old();\n name = \"Pepe\";\n};\n
This leads to a double call of prototype Npc_Default
which is considered an unsafe practice with undefined behaviour. The correct way is to call it like this:
instance pc_hero(C_NPC) // no prototype Npc_Default\n{\n pc_hero_old();\n name = \"Pepe\";\n}; \n
This way the prototype is called in the original function pc_hero_old()
and not for the second time when creating the new hooked instance."},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#dialogue-hook-example","title":"Dialogue hook example","text":"The hooking mechanism is designed to introduce new dialogues into the game as well as replacing old ones with hooks. The scripter can create new merchants, quests, dialogues, as well as attach svm phrases to them.
All new or replaced dialogues will immediately become available, including from saves. In the event that new dialogs are disabled (plugin or script removed), the engine will continue to keep them in the save file, which will allow the dialogs to return at any time with the same state they were in the last time.
Warning
Currently not working as intended (I think). The old dialogue is still used and as a result you will end up with both the old and the new dialogue (unless you edit the old condition function).
instance DIA_XARDAS_HELLO(C_INFO)\n{\n DIA_XARDAS_HELLO_old();\n important = FALSE;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/meta/","title":"META block","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/meta/#meta-block","title":"META block","text":"The META block is optional. If it is specified, it has to be the very first thing in the file without any indent or a comment above it.
Syntax:
META\n{\n Parser // specifies into which compiled file the scripts are going to be injected\n /*\n Code Name DAT file\n --- ------ -------\n Game parser Gothic.dat\n SFX parserSoundFX SFX.dat\n PFX parserParticleFX ParticleFX.dat\n VFX parserVisualFX VisualFX.dat\n Camera parserCamera Camera.dat\n Menu parserMenu Menu.dat\n Music parserMusic Music.dat\n */\n MergeMode // 0 - if conflict occurs = compilation error, 1 - if conflict occurs = hook\n Engine // comma separated list of engines for which the scripts will be injected \n /*\n Code Engine Human readable name\n --- ----- -----------------------\n G1 Gothic I Gothic I Classic\n G1A Gothic Sequel Gothic I Addon <3\n G2 Gothic II Gothic II Classic\n G2A Gothic II NoTR Gothic II Addon\n */\n\n NativeWhile // use native while\n Namespace // namespace of this script file\n Using // comma separated list of namespaces, that are considered local for this script file\n Mod // specify for which mod should this code be injected\n After // comma separated list of scripts, after which this script should be parsed\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/","title":"Other functions of the extender","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#other-functions-of-the-extender","title":"Other functions of the extender","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#ini-parameters","title":"ini parameters","text":"The choice of ini file depends on how the game was launched. If it was launched from Gothic.exe, then the parameters will be read from SystemPack.ini
. If it was launched through GothicStarter.exe, then they will be read from the ini of the mod.
[zParserExtender]\nLoadScript(obsolete) =\n;specifies a parser-script format script to run the scripts. The parameter is currently invalid.\n\nMergeMode = True\n;specifies whether injections will produce hooks.\n\nCompileDat = False\n;Determines if a copy of DAT file which has been modified by injection will be created.\n\nCompileOU = False\n;determines if a copy of an injection-modified OU file will be created.\n\nNativeWhile = False\n;Determines if a WHILE loop will be compiled. Defaults to False (for Ninja compatibility).\n\nMessagesLevel = 1\n;sets the output level. The higher the level, the more information will be printed to the debug console.\n\nStringIndexingMode = -1\n;defines string indexing mode (see string indexing). Default value is -1.\n;Default = -1 - The default mode for the moment is Repair mode.\n;Disabled = 0 - Do nothing with the indices.\n;TopSymbol = 1 - The plugin finds the uppermost unnamed string and sets a counter for it.\n;Repair = 2 - The plugin goes through the whole string table and, if the indexing order is broken, puts the correct names. The counter is set on the basis of the search.\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#marvin-console-commands","title":"MARVIN console commands","text":"zParserExtender adds console commands that save copies of the .dat
files with the injected code.
Warning
If the mod uses Ikarus, the CompileDat
option (in the .ini
file) should be used since a fatal error may occur when using the command.
Parser SaveDat OU - exports OU.Edited.bin\nParser SaveDat Game - exports Gothic.Edited.dat\nParser SaveDat SFX - exports SFX.Edited.dat\nParser SaveDat PFX - exports ParticleFX.Edited.dat\nParser SaveDat VFX - exports VisualFX.Edited.dat\nParser SaveDat Camera - exports Camera.Edited.dat\nParser SaveDat Menu - exports Menu.Edited.dat\nParser SaveDat Music - exports Music.Edited.dat\nParser Export Stringlist - exports the full string table to Scripts\\Exports\\StringList.d\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#launch-options","title":"Launch options","text":"Command line parameters can be passed to the game's exe via the command line or using GothicStarter_Mod.
zReparse_OU - parses and creates OU.bin\nzReparse_Game - parses and creates Gothic.dat\nzReparse_SFX - parses and creates SFX.dat\nzReparse_PFX - parses and creates ParticleFX.dat\nzReparse_VFX - parses and creates VisualFX.dat\nzReparse_Camera - parses and creates Camera.dat\nzReparse_Menu - parses and creates Menu.dat\nzReparse_Music - parses and creates Music.dat\n
Note
If you want to compile OU, you also have to include the Game parameter
-zReparse_Game -zReparse_OU
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#const-array-access","title":"Const array access","text":"The original zParser doesn't allow direct access to const string
arrays. zParserExtender allows you to do so.
Example:
func event GameInit()\n{\n Hlp_MessageBox(TXT_INV_CAT[4]); // Prints \"Artifacts\"\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#other-engine-fixes","title":"Other engine fixes","text":" When creating an item instance, the instance is placed into the global item
instance On DAT file load, the engine restores the original symbol hierarchy When loading a save, the engine now skips unknown symbols, instead of crashing "},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/","title":"Sign post teleportation","text":""},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#sign-post-teleportation","title":"Sign post teleportation","text":"This is a short \"problem-solving\" example, where we try to demonstrate the power of Daedalus injection using zParserExtender. GaroK asked me if there is a way to teleport to all the sign posts in Khorinis to gather information for a Gothic wiki article. The goal is to introduce a function that will teleport you to every signpost in Khorinis with the press of a button.
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#the-problem","title":"The problem","text":"In ZenGin you can teleport to named game objects with the goto vob {vobname}
command. But since the signposts do not have a vobname defined, I had to figure out a different approach.
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#ascii-zen","title":"ASCII ZEN","text":"We want to get all the signposts position from Khorinis. The game world was loaded into one of the available world editor, I found one of the signposts and noted the visual
which dictates the model of the in-game object nw_misc_sign_01.3DS
. Alternatively, you can find the standard vanilla objects from both games on this website. Next, the world was saved as a ASCII ZEN
format. This allows us to write a macro to search for all instances of objects with a specific visual and extract the position vector.
One signpost object[% oCMOB:zCVob 47105 317]\n pack=int:0\n presetName=string:\n bbox3DWS=rawFloat:7564.8291 127.361191 -80.5309067 7611.52441 377.422913 1.67681122 \n trafoOSToWSRot=raw:73e1673f9c4ec33b15efd8be4465d7bba0fe7f3f30ea7137e5edd83eecaa353bb7e2673f\n trafoOSToWSPos=vec3:7588.17627 252.391052 -39.4283791\n vobName=string:\n visual=string:NW_MISC_SIGN_01.3DS\n showVisual=bool:1\n visualCamAlign=enum:0\n visualAniMode=enum:0\n visualAniModeStrength=float:0\n vobFarClipZScale=float:1\n cdStatic=bool:1\n cdDyn=bool:1\n staticVob=bool:1\n dynShadow=enum:0\n zbias=int:0\n isAmbient=bool:0\n [visual zCProgMeshProto 53505 318]\n []\n [ai % 0 0]\n []\n focusName=string:MOBNAME_INCITY02\n hitpoints=int:10\n damage=int:0\n moveable=bool:0\n takeable=bool:0\n focusOverride=bool:0\n soundMaterial=enum:0\n visualDestroyed=string:\n owner=string:\n ownerGuild=string:\n isDestroyed=bool:0\n[]\n
Tip
You can also see that the focusName
has a MOBNAME_INCITY02
string constant. This constant is defined in the scripts and its content is used as the focus name.
const string MOBNAME_INCITY02 = \"To Marketplace\";\n
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#the-injectable-script","title":"The injectable script","text":"As it is an injectable script, we have to specify the META
tag. Lets tell zParserExtender to insert this code into the game parser.
META\n{\n Parser = Game\n};\n
We want to teleport the player and for this we will need the C_Position
and C_Vob_Data
classes. class C_Position\n{\n var int X; // X coordinate\n var int Y; // Y coordinate\n var int Z; // Z coordinate\n};\n\nclass C_VOB_DATA\n{\n var string Name; // object name\n var float VisualAlpha; // object's transparency 0.0 - 1.0\n var int ShowVisual; // display the mode\n var int DrawBBox3D; // show objects bounding box\n var int VisualAlphaEnabled; // enables objects transparency\n var int PhysicsEnabled; // enables object's physics\n var int IgnoredByTraceRay; // allow any object collisions\n var int CollDetectionStatic; // allow collision with static world polygons\n var int CollDetectionDynamic; // allow collision with dynamic world objects\n var int CastDynShadow; // display shadow of the object\n var int LightColorStatDirty; // allow static lighting of the object\n var int LightColorDynDirty; // allow dynamic lighting of the object\n var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only)\n var int DontWriteIntoArchive; // turns of the serialization of this object to the save file \n};\n
It turns out there is 54 instances of objects with the desired visual. Let us define const int NUM_OF_SIGNS = 54
and a const int MAX_COORDS = 3 * NUM_OF_SIGNS
- we will store 3 times 54 integers - for every signpost a x
, y
and z
coordinate. And lastly a const int
array containing all the positions. // Number of signs we want to jump to\nconst int NUM_OF_SIGNS = 54;\nconst int MAX_COORDS = 3 * NUM_OF_SIGNS;\n\nconst int sign_coordinates[MAX_COORDS] = {\n 11974, 309, 6815,\n 12024, 310, 6778,\n 12411, 1668, -22495,\n 19491, 1281, 1669,\n 19563, 1281, 1687,\n 20294, 2058, 12487,\n 20324, 2058, 12419,\n 21917, 2900, -22751,\n 2600, -57, -4351,\n 26695, 2419, 4308,\n 26770, 2418, 4319,\n 26978, 2937, 6130,\n 27015, 2936, 6104,\n 27049, 2937, 6159,\n 2964, 2142, 14424,\n 31383, 3896, 4699,\n 31427, 3896, 4640,\n 35368, 3870, -4374,\n 35435, 3870, -4355,\n 35437, 3871, -4399,\n 36205, 3333, -27186,\n 37774, 3875, -501,\n 37812, 3874, -469,\n 37849, 3874, -512,\n 38291, 3732, -6699,\n 39276, 3926, -3357,\n 39307, 3924, -3313,\n 39351, 3924, -3359,\n 39435, 4350, 10902,\n 39458, 4350, 10827,\n 40932, 3861, -3054,\n 42454, 2838, -19437,\n 5297, 387, -2145,\n 5358, 387, -2184,\n 5362, 387, -2128,\n 54006, 1723, -10316,\n 54035, 1723, -10387,\n 551, -62, -1820,\n 61080, 2132, -11622,\n 61155, 2132, -11625,\n 6408, 392, 3598,\n 6432, 393, 3652,\n 7000, 387, -1482,\n 73439, 3341, -11307,\n 7588, 252, -39,\n 7590, 252, -109,\n 7642, 253, -83,\n 7713, 387, -4782,\n 7758, 386, -4775,\n 7776, 388, -4811,\n 8154, 1206, -17022,\n 8855, 395, -2402,\n 9704, 393, 5129,\n 9738, 392, 5108\n};\n
Next define a built in event GameLoop
function, to check for a pressed key. If the key U
is pressed, the jump_to_sign
function is called. // check for pressed U button every frame\nfunc event GameLoop()\n{\n // if U is toggled, run the function\n if (Hlp_KeyToggled(KEY_U))\n {\n jump_to_sign();\n };\n};\n
Let's look at the jump_to_sign
function now. This function is called on every U
key press and goes through all the signposts and teleports the player to them. At the start of the function we check if the index is not out of bounds and if it is, sets it back to 0 and starts over.
// if we reached the end, start over\n if (tp_index >= NUM_OF_SIGNS)\n {\n tp_index = 0;\n };\n
Notice the use of Str_Format
function for the formatted output. // give information to the player\nPrint(Str_Format(\"Sign %i/%i\", tp_index+1, NUM_OF_SIGNS));\n\nvar C_Position pos; pos = Vob_GetVobPosition(hero);\nvar C_Vob_Data data; data = Vob_GetVobData(hero);\n
Daedalus does not allow array access with variables (only constants and literals). To access the coordinate array we use a selection of parser functions. Firstly we get the game parser ID. Then we can use the Par_GetSymbolValueIntArray
to access the sign_coordinates
array and assign the coordinates to the pos
variable. // get parser ID for the GAME parser\nvar int game_par_id; game_par_id = Par_GetParserID(\"game\");\n\n// get parser ID of the array\nvar int arr_id; arr_id = Par_GetSymbolID(game_par_id ,\"sign_coordinates\");\n\n// access the coordinates from above array\npos.x = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 ); \npos.y = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 + 1);\npos.z = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 + 2);\n
And now comes the big trick. If you try to just change the position the dynamic and static collision is going to stop you at the first wall, tree or a mountain. To disable it, we can use the C_Vob_Data
helper class, get players data, and disable both the static a dynamic collision. First we create a backup of the values just so we can restore them back after the teleport. // backup original collision detection\nvar int dyn; dyn = data.CollDetectionDynamic;\nvar int stat; stat = data.CollDetectionStatic;\n\n// turn off collision detection \ndata.CollDetectionDynamic = 0;\ndata.CollDetectionStatic = 0;\n
Let us apply the changed data to the player and edit the position. // apply the edited data to player\nVob_SetVobData(hero, data);\n\n// move the player \nVob_SetVobPosition(hero, pos);\n
Restore the collision detection data from the backup we made and set it. // restore collision detection\ndata.CollDetectionDynamic = dyn;\ndata.CollDetectionStatic = stat;\n\n// apply the edited data to player\nVob_SetVobData(hero, data);\n
Finally, we advance the index to jump to another signpost. // advance the index\ntp_index += 1;\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/","title":"AI - functions for working with AI","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai---functions-for-working-with-ai","title":"AI - functions for working with AI","text":"Functions to work with the new C_Trigger
class and NPC's AI queue.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_callscript","title":"AI_CallScript
","text":"AI_CallScript
Adds a funcName
function call to the AI queue
func void AI_CallScript(var string funcName,\n var C_NPC slf,\n var C_NPC oth) {};\n
funcName
- name of the function to be called slf
- will be inserted into global self
instance oth
- will be inserted into global other
instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_starttriggerscript","title":"AI_startTriggerScript
","text":"AI_startTriggerScript
Creates a trigger script that calls function funcName
once every interval
in milliseconds
func C_Trigger AI_startTriggerScript(var string funcName, var int interval) {};\n
funcName
- name of the function to be called interval
- call period in milliseconds return
- created C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_starttriggerscriptex","title":"AI_startTriggerScriptEx
","text":"AI_startTriggerScriptEx
Extended version call - Creates a trigger script, that calls function funcName
once every interval
in milliseconds also updates the self
, other
and victim
global instances based on slf
, oth
and vct
parameters respectively
func C_Trigger AI_startTriggerScriptEx( var string funcName,\n var int interval,\n var C_NPC slf,\n var C_NPC oth,\n var C_NPC vct) {};\n
funcName
- name of the function to be called interval
- call period in milliseconds slf
- will be inserted into global self
instance oth
- will be inserted into global other
instance vct
- will be inserted into global victim
instance return
- created C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerbyid","title":"AI_GetTriggerByID
","text":"AI_GetTriggerByID
Returns a C_Trigger instance from the array of active triggers by the array index ID
func C_Trigger AI_GetTriggerByID(var int ID) {};\n
ID
- array id return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggersnum","title":"AI_GetTriggersNum
","text":"AI_GetTriggersNum
Returns the number of active C_Trigger scripts
func int AI_GetTriggersNum() {};\n
return
- number of active C_Trigger scripts "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggernpc","title":"AI_GetTriggerNPC
","text":"AI_GetTriggerNPC
Returns the npc associated with the C_Trigger script based on the ID selfID = 0; otherID = 1; victimID = 2;
func C_NPC AI_GetTriggerNPC(var C_Trigger trigger, var int npcID) {};\n
trigger
- C_Trigger script npcID
- NPC id return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerfunc","title":"AI_GetTriggerFunc
","text":"AI_GetTriggerFunc
Returns the function associated with the specified C_Trigger
func func AI_GetTriggerFunc(var C_Trigger trigger) {};\n
trigger
- C_Trigger script return
- trigger function "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerfuncname","title":"AI_GetTriggerFuncName
","text":"AI_GetTriggerFuncName
Returns the function name of a function associated with the specified C_Trigger
func string AI_GetTriggerFuncName(var C_Trigger trigger) {};\n
trigger
- C_Trigger script return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyfunc","title":"Ai_GetNextTriggerByFunc
","text":"Ai_GetNextTriggerByFunc
Returns the next trigger in the active trigger array based on the trigger function, starting on the startTrigger
trigger
func C_Trigger Ai_GetNextTriggerByFunc(var C_Trigger startTrigger, var func function) {};\n
startTrigger
- C_Trigger script to start the search from function
- function to be matched return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyfuncname","title":"Ai_GetNextTriggerByFuncName
","text":"Ai_GetNextTriggerByFuncName
Returns the next trigger in the active trigger array based on the trigger function name, starting on the startTrigger
trigger
func C_Trigger Ai_GetNextTriggerByFuncName(var C_Trigger startTrigger, var string functionName) {};\n
startTrigger
- C_Trigger script to start the search from functionName
- name of a function to be matched return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyself","title":"Ai_GetNextTriggerBySelf
","text":"Ai_GetNextTriggerBySelf
Returns the next trigger in the active trigger array based on the self
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerBySelf(var C_Trigger startTrigger, var C_NPC self) {};\n
startTrigger
- C_Trigger script to start the search from self
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyother","title":"Ai_GetNextTriggerByOther
","text":"Ai_GetNextTriggerByOther
Returns the next trigger in the active trigger array based on the other
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerByOther(var C_Trigger startTrigger, var C_NPC other) {};\n
startTrigger
- C_Trigger script to start the search from other
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyvictim","title":"Ai_GetNextTriggerByVictim
","text":"Ai_GetNextTriggerByVictim
Returns the next trigger in the active trigger array based on the victim
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerByVictim( var C_Trigger startTrigger, var C_NPC victim ) {};\n
startTrigger
- C_Trigger script to start the search from victim
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbynpcs","title":"Ai_GetNextTriggerByNPCs
","text":"Ai_GetNextTriggerByNPCs
Returns the next trigger in the active trigger array based on all the NPCs set in the trigger script self
, other
and victim
, starting on the startTrigger
instance set in the trigger
func c_trigger Ai_GetNextTriggerByNPCs( var C_Trigger startTrigger,\n var C_NPC self,\n var C_NPC other,\n var C_NPC victim) {};\n
startTrigger
- C_Trigger script to start the search from self
- self C_NPC instance other
- other C_NPC instance victim
- victim C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/","title":"CAST - data type conversion functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast---data-type-conversion-functions","title":"CAST - data type conversion functions","text":"External functions for data type conversion and pointer casting.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertoinstance","title":"Cast_PointerToInstance
","text":"Cast_PointerToInstance
Converts memory address (pointer) to an instance
func instance Cast_PointerToInstance(var int address) {};\n
address
- object pointer return
- instance of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instancetopointer","title":"Cast_InstanceToPointer
","text":"Cast_InstanceToPointer
Converts instance to a memory address (pointer)
func int Cast_InstanceToPointer( var instance object) {};\n
object
- object instance return
- memory address (pointer) of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertonpc","title":"Cast_PointerToNpc
","text":"Cast_PointerToNpc
Casts memory address (pointer) to an NPC
func C_NPC Cast_PointerToNpc( var int address) {};\n
address
- npc pointer return
- NPC instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertoitem","title":"Cast_PointerToItem
","text":"Cast_PointerToItem
Casts memory address (pointer) to an Item
func C_ITEM Cast_PointerToItem( var int address) {};\n
address
- item pointer return
- Item instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceisnpc","title":"Cast_InstanceIsNpc
","text":"Cast_InstanceIsNpc
Checks whether object is an NPC
func int Cast_InstanceIsNpc( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceisitem","title":"Cast_InstanceIsItem
","text":"Cast_InstanceIsItem
Checks whether object is an Item
func int Cast_InstanceIsItem( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceismob","title":"Cast_InstanceIsMob
","text":"Cast_InstanceIsMob
Checks whether object is an MOB
func int Cast_InstanceIsMob( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getinstanceindex","title":"Cast_GetInstanceIndex
","text":"Cast_GetInstanceIndex
Returns symbolID of the object, returns -1 when not found
func int Cast_GetInstanceIndex( var instance object) {};\n
object
- instance of an object return
- symbol table index, -1 when not found "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getclassid","title":"Cast_GetClassID
","text":"Cast_GetClassID
Returns the class identifier of a class by its name
func int Cast_GetClassID( var string className ) {};\n
className
- name of the class return
- class identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getvobclassid","title":"Cast_GetVobClassID
","text":"Cast_GetVobClassID
Returns class identifier of the zCObject vob class
func int Cast_GetVobClassID( var instance object ) {};\n
object
- object instance return
- class zCObject identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_checkvobclassid","title":"Cast_CheckVobClassID
","text":"Cast_CheckVobClassID
Checks if the classId class is the parent class of the object
func int Cast_CheckVobClassID( var int classId, var instance object ) {};\n
classId
- class identifier, from Cast_GetClassID function object
- object instance return
- class zCObject identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/events_vars/","title":"Event functions and variables","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/events_vars/#event-functions-and-variables","title":"Event functions and variables","text":"On top of external functions, zParserExtender also adds these event functions and constants.
/// Every event function with this name is executed once every frame\nfunc event GameLoop() {};\n\n/// Every event function with this name is executed once on game init\nfunc event GameInit() {};\n\n/// empty instance\nconst instance null;\n\n/// not a number floating point constant\nconst float NaN;\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/","title":"HLP - help functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp---help-functions","title":"HLP - help functions","text":"Helper functions generally used for safety checks, to get specific information from the engine or to interface with the configuration .ini
files.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_hasfocusvob","title":"Hlp_HasFocusVob
","text":"Hlp_HasFocusVob
Returns TRUE
, if a specified NPC has a Vob in focus
func int Hlp_HasFocusVob( var C_NPC npc ) {};\n
npc
- NPC return
- TRUE
if npc has a focus Vob, FALSE
if it does not "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getfocusvob","title":"Hlp_GetFocusVob
","text":"Hlp_GetFocusVob
Returns NPC's focus Vob
func instance Hlp_GetFocusVob( var C_NPC npc ) {};\n
npc
- NPC return
- focus vob "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getfocusvobname","title":"Hlp_GetFocusVobName
","text":"Hlp_GetFocusVobName
Returns the name of NPC's focus vob
func string Hlp_GetFocusVobName( var C_NPC npc ) {};\n
npc
- NPC return
- focus vob name "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getstringlength","title":"Hlp_GetStringLength
","text":"Hlp_GetStringLength
Returns the length of a specified string
func int Hlp_GetStringLength( var string str ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#isnan","title":"IsNAN
","text":"IsNAN
Checks whether floating point number is valid
func int IsNAN( var float value ) {};\n
return
- TRUE
if value
is NaN, FALSE
if value
is a valid floating point number "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_keytoggled","title":"Hlp_KeyToggled
","text":"Hlp_KeyToggled
Checks whether key
is toggled
func int Hlp_KeyToggled( var int key ) {};\n
key
- key code return
- TRUE
if key is toggled, FALSE
if key is not toggled "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_keypressed","title":"Hlp_KeyPressed
","text":"Hlp_KeyPressed
Checks whether key
is pressed
func int Hlp_KeyPressed( var int key ) {};\n
key
- key code return
- TRUE
if key is pressed, FALSE
if key is not pressed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_logicalkeytoggled","title":"Hlp_LogicalKeyToggled
","text":"Hlp_LogicalKeyToggled
Checks whether logical key
is toggled
func int Hlp_LogicalKeyToggled( var int key ) {};\n
key
- key code return
- TRUE
if key is toggled, FALSE
if key is not toggled "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_gameonpause","title":"Hlp_GameOnPause
","text":"Hlp_GameOnPause
Checks whether the game is paused
func int Hlp_GameOnPause() {};\n
return
- TRUE
if the game is paused, FALSE
if the game is not paused "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_messagebox","title":"Hlp_MessageBox
","text":"Hlp_MessageBox
Opens a message box with a specified message
func void Hlp_MessageBox( var string message ) {};\n
message
- message to be printed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_printconsole","title":"Hlp_PrintConsole
","text":"Hlp_PrintConsole
Prints a message to the Union debug console
func void Hlp_PrintConsole(var string message) {};\n
message
- message to be printed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_optionisexists","title":"Hlp_OptionIsExists
","text":"Hlp_OptionIsExists
Checks whether the entry
in section
in .ini
file optName
exists
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func int Hlp_OptionIsExists(var string optName, var string section, var string entry) {};\n
optName
- the .ini
file section
- settings section like [GAME]
entry
- one setting entry like playLogoVideos
return
- TRUE
if the option exists, FALSE
if the option does not exist "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionint","title":"Hlp_ReadOptionInt
","text":"Hlp_ReadOptionInt
Read an integer value from specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func int Hlp_ReadOptionInt(var string optName, var string section, var string entry, var int default) {};\n
optName
- the .ini
file section
- settings section like [GAME]
entry
- one setting entry like playLogoVideos
default
- default value - if the value is empty return
- the option value "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionfloat","title":"Hlp_ReadOptionFloat
","text":"!!! function \"`Hlp_ReadOptionFloat`\"\nRead a floating point value from specified `.ini` file, section and entry.\n\n`optName` values\n\n- `#!dae \"Gothic\"`\n- `#!dae \"Mod\"`\n- `#!dae \"SystemPack\"`\n\n```dae\nfunc float Hlp_ReadOptionFloat(var string optName, var string section, var string entry, var float default) {};\n```\n\n- `optName` - the `.ini` file\n- `section` - settings section like `[INTERFACE]`\n- `entry` - one setting entry like `scale`\n- `default` - default value - if the value is empty\n- `return` - the option value\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionstring","title":"Hlp_ReadOptionString
","text":"Hlp_ReadOptionString
Read a string value from specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func string Hlp_ReadOptionString(var string optName, var string section, var string entry, var string default) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
default
- default value - if the value is empty return
- the option value "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionint","title":"Hlp_WriteOptionInt
","text":"Hlp_WriteOptionInt
Writes an integer value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionInt(var string optName, var string section, var string entry, var int value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionfloat","title":"Hlp_WriteOptionFloat
","text":"Hlp_WriteOptionFloat
Writes a floating point value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionFloat(var string optName, var string section, var string entry, var float value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionstring","title":"Hlp_WriteOptionString
","text":"Hlp_WriteOptionString
Writes a string value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionString(var string optName, var string section, var string entry, var string value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getsteampersonalname","title":"Hlp_GetSteamPersonalName
","text":"Hlp_GetSteamPersonalName
Returns the name of the current Steam user Returns empty string when not run with Steam
func string Hlp_GetSteamPersonalName() {};\n
return
- string containing the Steam username, or an empty string "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_doevent","title":"Hlp_DoEvent
","text":"Hlp_DoEvent
Calls every event function with the name funcName
.
func void Hlp_DoEvent(var string funcName) {};\n
funcName
- name of the event function to be called (all of them). "},{"location":"zengin/scripts/extenders/zparserextender/externals/log/","title":"Log functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log-functions","title":"Log functions","text":"As discussed on Inside Gothic, vanilla Gothic has no way of getting the status of a quest. These functions implement that functionality.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log_gettopicstatus","title":"Log_GetTopicStatus
","text":"Log_GetTopicStatus
Returns the status of diary topic
-1
- Not found 0
- Free 1
- Running 2
- Success 3
- Failure 4
- Obsolete func int Log_GetTopicStatus(var string topic) {};\n
topic
- name of the topic return
- topic status "},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log_gettopicsection","title":"Log_GetTopicSection
","text":"Log_GetTopicSection
Returns the topic the diary topic is in
-1
- Not found 0
- Missions 1
- Notes 2
- All func int Log_GetTopicSection(var string topic) {};\n
topic
- name of the topic return
- topic section "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/","title":"MDL - model functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl---model-functions","title":"MDL - model functions","text":"Functions to tweak animation and other model related settings.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_getanimationindex","title":"Mdl_GetAnimationIndex
","text":"Mdl_GetAnimationIndex
Returns animation's index for specified NPC based on animation's name
func int Mdl_GetAnimationIndex( var C_NPC npc, var string ani_name ) {};\n
npc
- NPC with the animation ani_name
- name of the animation in uppercase return
- animation index "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_getanimationname","title":"Mdl_GetAnimationName
","text":"Mdl_GetAnimationName
Returns animation's name for specified NPC based on animation's index
func string Mdl_GetAnimationName( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- animation name "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_animationisexists","title":"Mdl_AnimationIsExists
","text":"Mdl_AnimationIsExists
Checks whether animation exists
func int Mdl_AnimationIsExists( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- animation name "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_animationisactive","title":"Mdl_AnimationIsActive
","text":"Mdl_AnimationIsActive
Checks whether animation is active (whether it is currently played)
func int Mdl_AnimationIsActive( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- TRUE
if the animation is playing, FALSE
if it is not playing "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setallanimationsfps","title":"Mdl_SetAllAnimationsFPS
","text":"Mdl_SetAllAnimationsFPS
Set framerate for all animations
func void Mdl_SetAllAnimationsFPS( var C_NPC npc, var float fps ) {};\n
npc
- NPC with the animation fps
- framerate "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetallanimationsfps","title":"Mdl_ResetAllAnimationsFPS
","text":"Mdl_ResetAllAnimationsFPS
Reset framerate for all animations to default value
func void Mdl_ResetAllAnimationsFPS( var C_NPC npc ) {};\n
npc
- NPC with the animation "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setanimationfps","title":"Mdl_SetAnimationFPS
","text":"Mdl_SetAnimationFPS
Set framerate for animation specified by animation index
func void Mdl_SetAnimationFPS( var C_NPC npc, var int ani_index, var float fps ) {};\n
npc
- NPC with the animation ani_index
- animation index fps
- framerate "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetanimationfps","title":"Mdl_ResetAnimationFPS
","text":"Mdl_ResetAnimationFPS
Reset framerate to default for animation specified by animation index
func void Mdl_ResetAnimationFPS( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setvisible","title":"Mdl_SetVisible
","text":"Mdl_SetVisible
Set NPCs visibility
func void Mdl_SetVisible( var C_NPC npc, var int isVisible ) {};\n
npc
- specified NPC isVisible
- TRUE
- visible, FALSE
- invisible "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_applyoverlaymds_atfirst","title":"Mdl_ApplyOverlayMds_AtFirst
","text":"Mdl_ApplyOverlayMds_AtFirst
Applies or moves existing overlay to the top of the list
func void Mdl_ApplyOverlayMds_AtFirst( var string mdsName ) {};\n
mdsName
- name of the overlay "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setnpcspeedmultiplier","title":"Mdl_SetNpcSpeedMultiplier
","text":"Mdl_SetNpcSpeedMultiplier
Sets a multiplier for animation speed 1.0 = 100% speed (normal speed)
func void Mdl_SetNpcSpeedMultiplier( var C_Npc npc, var float multiplier ) {};\n
npc
- npc to be affected multiplier
- speed of the animation "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetnpcspeedmultiplier","title":"Mdl_ResetNpcSpeedMultiplier
","text":"Mdl_ResetNpcSpeedMultiplier
Resets the animation speed of an NPC
func void Mdl_ResetNpcSpeedMultiplier( var C_Npc npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/","title":"Menu function","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#menu-function","title":"Menu function","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#menu_searchitems","title":"Menu_SearchItems
","text":"Menu_SearchItems
Find all C_MenuItem object instances by the mask and automatically places them in the current menu instance
func void Menu_SearchItems( var string mask ) {};\n
mask
- regex like mask for searching "},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#example","title":"Example","text":"This function is used in the Union Menu API script. In this script the Menu_SearchItems
external is used to collect all Union menu scripts that are placed into the Union & Plugins menu that will appear in the game if you use any of the plugins that use this feature.
Usage of Menu_SearchItems external functioninstance MENU_OPT_UNION(C_MENU_DEF)\n{\n Menu_SearchItems(\"MENUITEM_UNION_AUTO_*\");\n MENU_OPT_UNION_PY = 1200;\n backpic = MENU_BACK_PIC;\n items[0] = \"UNION_MENUITEM_TITLE\";\n items[100] = \"UNION_MENUITEM_BACK\";\n defaultoutgame = 0;\n defaultingame = 0;\n Flags = Flags | MENU_SHOW_INFO;\n};\n
In this case all instances are of the name MENUITEM_UNION_AUTO_*
where *
is a wildcard that can be substituted with anything. The plugin will search the scripts and find all instances (in the case of zGamePad it is MenuItem_Union_Auto_zGamePad
)
This example comes from the zUnionMenu.d
injectable API script that is part of the zGamePad plugin, GitHub link.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/","title":"MOB - interactive object functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob---interactive-object-functions","title":"MOB - interactive object functions","text":"Functions to manipulate interactive objects like destroying MOBs, setting lockpick combination and such.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_destroy","title":"Mob_Destroy
","text":"Mob_Destroy
Marks oCMOB as destroyed, changes the visual to visualDestroyed (if present).
func void Mob_Destroy( var instance object ) {};\n
object
- oCMOB to be destroyed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_removeitem","title":"Mob_RemoveItem
","text":"Mob_RemoveItem
Removes an item from a oCMobContainer
func void Mob_RemoveItem( var instance object, var int item ) {};\n
object
- oCMobContainer object item
- item to be removed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_removeitems","title":"Mob_RemoveItems
","text":"Mob_RemoveItems
Removes specified number of items from a oCMobContainer
func void Mob_RemoveItems( var instance object, var int item, var int cnt ) {};\n
object
- oCMobContainer object item
- item to be removed cnt
- number of items to be removed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_insertitem","title":"Mob_InsertItem
","text":"Mob_InsertItem
Inserts an item into a oCMobContainer
func void Mob_InsertItem( var instance object, var int item ) {};\n
object
- oCMobContainer object item
- item to be inserted "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_insertitems","title":"Mob_InsertItems
","text":"Mob_InsertItems
Inserts specified number of items into a oCMobContainer
func void Mob_InsertItems( var instance object, var int item, var int cnt ) {};\n
object
- oCMobContainer object item
- item to be inserted cnt
- number of items to be inserted "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_getlockcombination","title":"Mob_GetLockCombination
","text":"Mob_GetLockCombination
Returns a lock combination of a oCMobContainer
func string Mob_GetLockCombination( var instance object ) {};\n
object
- oCMobContainer object return
- lock combination "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setlockcombination","title":"Mob_SetLockCombination
","text":"Mob_SetLockCombination
Sets a lock combination to a oCMobContainer
func void Mob_SetLockCombination( var instance object, var string comb ) {};\n
object
- oCMobContainer object comb
- lock combination "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_islocked","title":"Mob_IsLocked
","text":"Mob_IsLocked
Returns TRUE
if the object is locked
func int Mob_IsLocked( var instance object ) {};\n
object
- oCMobLockable object return
- TRUE
if locked, FALSE
if unlocked "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setlocked","title":"Mob_SetLocked
","text":"Mob_SetLocked
Set the lock status of the object
func void Mob_SetLocked( var instance object, var int locked ) {};\n
object
- oCMobLockable object locked
- lock or unlock the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_getkeyinstance","title":"Mob_GetKeyInstance
","text":"Mob_GetKeyInstance
Returns the key instance, that unlocks the object
func instance Mob_GetKeyInstance( var instance object ) {};\n
object
- oCMobLockable object return
- the key C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setkeyinstance","title":"Mob_SetKeyInstance
","text":"Mob_SetKeyInstance
Stets the key instance, that unlocks the object
func void Mob_SetKeyInstance( var instance object, var int key ) {};\n
object
- oCMobLockable object key
- the key C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/","title":"NPC - character functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc---character-functions","title":"NPC - character functions","text":"NPC related functions.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_setashero","title":"Npc_SetAsHero
","text":"Npc_SetAsHero
Changes players character to specified npc
func void Npc_SetAsHero( var C_NPC npc ) {};\n
npc
- NPC to be set as players character "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventory","title":"Npc_OpenInventory
","text":"Npc_OpenInventory
Opens NPCs main inventory
func void Npc_OpenInventory( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventorysteal","title":"Npc_OpenInventorySteal
","text":"Npc_OpenInventorySteal
Opens the steal inventory of npc
's focus NPC
func void Npc_OpenInventorySteal( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventorytrade","title":"Npc_OpenInventoryTrade
","text":"Npc_OpenInventoryTrade
Start the trading dialogue with specified NPC
func void Npc_OpenInventoryTrade( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getlefthanditem","title":"Npc_GetLeftHandItem
","text":"Npc_GetLeftHandItem
Returns an item in NPC's left hand slot
func C_Item Npc_GetLeftHandItem( var C_Npc npc ) {};\n
npc
- npc to be affected return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getrighthanditem","title":"Npc_GetRightHandItem
","text":"Npc_GetRightHandItem
Returns an item in NPC's right hand slot
func C_Item Npc_GetRightHandItem( var C_Npc npc ) {};\n
npc
- npc to be affected return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getslotitem","title":"Npc_GetSlotItem
","text":"Npc_GetSlotItem
Returns an item from a slot with the slotName
func C_Item Npc_GetSlotItem( var C_Npc npc, var string slotName ) {};\n
npc
- npc to be affected slotName
- name of the slot return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_putinslot","title":"Npc_PutInSlot
","text":"Npc_PutInSlot
Places an instance of the oCVom class (including items and NPCs) object into the slotName of the NPC The copyInInv parameter determines whether a copy of the object should remain in the character's inventory
func void Npc_PutInSlot(var C_Npc npc, var string slotName, var instance object, var int copyInInv) {};\n
npc
- npc to remove the item from slotName
- name of the slot from which to remove the item object
- object to be inserted into the slot copyInInv
- should a copy of the object stay in character inventory "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_removefromslot","title":"Npc_RemoveFromSlot
","text":"Npc_RemoveFromSlot
Removes an object from the slotName of the NPC. The dropIt parameter in Gothic 2 defines, whether object should drop out of the slot. In Gothic 1, this parameter is reserved and must be 0.
func void Npc_RemoveFromSlot(var C_Npc npc, var string slotName, var int dropIt) {};\n
npc
- npc to remove the item from slotName
- name of the slot from which to remove the item dropIt
- should the object be dropped "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/","title":"PAR - functions for parser manipulation","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par---functions-for-parser-manipulation","title":"PAR - functions for parser manipulation","text":"Parser functions are used to manipulate the parsers. Retrieve SymbolID, access arrays and such.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getparserid","title":"Par_GetParserID
","text":"Par_GetParserID
Returns a parser ID of the parser with a parName
name
Parser names:
\"Game\"
\"SFX\"
\"PFX\"
\"VFX\"
\"Camera\"
\"Menu\"
\"Music\"
func int Par_GetParserID(var string parName) {};\n
parName
- parser name return
- parser ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolid","title":"Par_GetSymbolID
","text":"Par_GetSymbolID
Returns symbol ID for the symbol specified by its name
func int Par_GetSymbolID(var int parId, var string symName) {};\n
parID
- parser ID symName
- symbol name return
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbollength","title":"Par_GetSymbolLength
","text":"Par_GetSymbolLength
Returns symbol length (number of elements)
func int Par_GetSymbolLength(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol length "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueint","title":"Par_GetSymbolValueInt
","text":"Par_GetSymbolValueInt
Returns the integer value of specified symbol
func int Par_GetSymbolValueInt(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluefloat","title":"Par_GetSymbolValueFloat
","text":"Par_GetSymbolValueFloat
Returns the float value of specified symbol
func float Par_GetSymbolValueFloat(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluestring","title":"Par_GetSymbolValueString
","text":"Par_GetSymbolValueString
Returns the string value of specified symbol
func string Par_GetSymbolValueString(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueinstance","title":"Par_GetSymbolValueInstance
","text":"Par_GetSymbolValueInstance
Returns the instance value of specified symbol
func instance Par_GetSymbolValueInstance(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueintarray","title":"Par_GetSymbolValueIntArray
","text":"Par_GetSymbolValueIntArray
Returns the value of specified integer array at the arrayID
index
func int Par_GetSymbolValueIntArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluefloatarray","title":"Par_GetSymbolValueFloatArray
","text":"Par_GetSymbolValueFloatArray
Returns the value of specified float array at the arrayID
index
func float Par_GetSymbolValueFloatArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluestringarray","title":"Par_GetSymbolValueStringArray
","text":"Par_GetSymbolValueStringArray
Returns the value of specified string array at the arrayID
index
func string Par_GetSymbolValueStringArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueint","title":"Par_SetSymbolValueInt
","text":"Par_SetSymbolValueInt
Sets a new integer value to specified symbol
func void Par_SetSymbolValueInt(var int value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluefloat","title":"Par_SetSymbolValueFloat
","text":"Par_SetSymbolValueFloat
Sets a new float value to specified symbol
func void Par_SetSymbolValueFloat(var float value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluestring","title":"Par_SetSymbolValueString
","text":"Par_SetSymbolValueString
Sets a new string value to specified symbol
func void Par_SetSymbolValueString(var string value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueinstance","title":"Par_SetSymbolValueInstance
","text":"Par_SetSymbolValueInstance
Sets a new instance value to specified symbol
func void Par_SetSymbolValueInstance(var instance value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueintarray","title":"Par_SetSymbolValueIntArray
","text":"Par_SetSymbolValueIntArray
Sets a new integer value to specified integer array symbol
func void Par_SetSymbolValueIntArray(var int value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluefloatarray","title":"Par_SetSymbolValueFloatArray
","text":"Par_SetSymbolValueFloatArray
Sets a new float value to specified float array symbol
func void Par_SetSymbolValueFloatArray(var float value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluestringarray","title":"Par_SetSymbolValueStringArray
","text":"Par_SetSymbolValueStringArray
Sets a new string value to specified string array symbol
func void Par_SetSymbolValueStringArray(var string value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/","title":"String functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#string-functions","title":"String functions","text":"Functions to manipulate and format strings.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_format","title":"Str_Format
","text":"Str_Format
Returns formatted string using format specifiers
Format specifiers:
%s
- inserts a string %i
- inserts an integer number %x
- inserts an integer in hexadecimal %f
- inserts a floating point number %b
- inserts a logical expression %p
- inserts a pointer func string Str_Format( var string format, ... ) {};\n
return
- formatted string "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#examples","title":"Examples
","text":"Examples
Very powerful function, can be used to streamline strings used in the scripts as well as optimize them for translations.
Define constants containing the string with format specifiers.
const string MENU_SAVE = \"Slot %i - press ENTER to save in this slot.\";\nconst string MENU_LOAD = \"Slot %i - press ENTER to load saved game.\";\n
Then define two format functions as such:
func string GetSaveSlotString (var int number)\n{\n return Str_format(MENU_SAVE, number);\n};\n
func string GetLoadSlotString (var int number)\n{\n return Str_format(MENU_LOAD, number);\n};\n
Tip
Since the whole translatable string is saved in one constant, it is very easy for translators to change the word order. This was not possible to do without code change to the ConcatStrings
function calls within the scripts. With this simple change, translators have to translate only 2 strings instead of 30 (15 + 15 slots) and only 2 strings are compiled into the compiled Menu.dat
file.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlocalizedstring","title":"Str_GetLocalizedString
","text":"Str_GetLocalizedString
Returns a string in the current language, otherwise in English. Arguments MUST be encoded in UTF-8! The result string will be converted to appropriate ANSI string.
func string Str_GetLocalizedString( var string russian,\n var string english,\n var string german,\n var string polish ) {};\n
russian
- Russian string english
- English string german
- German string polish
- Polish string return
- string in the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlocalizedstringex","title":"Str_GetLocalizedStringEx
","text":"Str_GetLocalizedStringEx
Returns a string in the current language, otherwise in English. Offers additional languages
func string Str_GetLocalizedStringEx( var string russian,\n var string english,\n var string german,\n var string polish,\n var string romanian,\n var string italian,\n var string czech,\n var string spanish ) {};\n
russian
- Russian string english
- English string german
- German string polish
- Polish string romanian
- Romanian string italian
- Italian string czech
- Czech string spanish
- Spanish string return
- string in the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_utf8_to_ansi","title":"Str_UTF8_to_ANSI
","text":"Str_UTF8_to_ANSI
Converts UTF-8 string into an ANSI string with codePage
func string Str_UTF8_to_ANSI( var string utf8, var int codePage ) {};\n
utf8
- string encoded in UTF8 codePage
- codePage id, can be obtained from Str_GetCurrentCP return
- "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getcurrentcp","title":"Str_GetCurrentCP
","text":"Str_GetCurrentCP
Return the code page corresponding to the current language set in the Union System
func int Str_GetCurrentCP() {};\n
return
- code page corresponding to the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlength","title":"Str_GetLength
","text":"Str_GetLength
Returns the length of a string
func int Str_GetLength( var int str ) {};\n
str
- string to be measured return
- length of the string "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/","title":"VOB - functions for object manipulation","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob---functions-for-object-manipulation","title":"VOB - functions for object manipulation","text":"VOB functions allow you to manipulate game world objects.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getvobposition","title":"Vob_GetVobPosition
","text":"Vob_GetVobPosition
Returns the current position of the object in the world
func C_Position Vob_GetVobPosition( var C_Vob vob ) {};\n
vob
- vob to ge the position of return
- C_Position instance - position of the VOB "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setvobposition","title":"Vob_SetVobPosition
","text":"Vob_SetVobPosition
Sets the current position of the object in the world
func void Vob_SetVobPosition( var C_Vob vob, var C_Position pos ) {};\n
vob
- vob to get the position of pos
- new position of the vob "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getvobdata","title":"Vob_GetVobData
","text":"Vob_GetVobData
Returns the universal data of the zCVob object
func C_Vob_Data Vob_GetVobData( var C_Vob vob ) {};\n
vob
- VOB to get the position of return
- general vob data C_Vob_Data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setvobdata","title":"Vob_SetVobData
","text":"Vob_SetVobData
Sets the universal data to a zCVob object
func void Vob_SetVobData( var C_Vob vob, var C_Vob_Data data ) {};\n
vob
- VOB to get the position of data
- general vob data C_Vob_Data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getlightdata","title":"Vob_GetLightData
","text":"Vob_GetLightData
Returns zCVobLight object data
func C_Light_Data Vob_GetLightData( var C_Vob vobLight ) {};\n
vobLight
- vobLight object return
- C_Light_Data of the light "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setlightdata","title":"Vob_SetLightData
","text":"Vob_SetLightData
Sets the data of a zCVobLight object
func void Vob_SetLightData( var C_Vob vobLight, var C_Light_Data data ) {};\n
vobLight
- object to apply the light data to data
- C_Light_Data light data to be set "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_clearlightanilist","title":"Vob_ClearLightAniList
","text":"Vob_ClearLightAniList
Clears the list of animation colours for the light source
func void Vob_ClearLightAniList( var C_Vob vobLight ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_addlightanicolor","title":"Vob_AddLightAniColor
","text":"Vob_AddLightAniColor
Adds a color to the colour list
func void Vob_AddLightAniColor( var C_Vob vobLight, var C_Color col ) {};\n
vobLight
- object to apply the colour to col
- colour to be applied "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_addlightanicolorrgb","title":"Vob_AddLightAniColorRGB
","text":"Vob_AddLightAniColorRGB
Adds a color to the colour list
func void Vob_AddLightAniColorRGB( var C_Vob vobLight,\n var int r,\n var int g,\n var int b ) {};\n
vobLight
- object to apply the colour to r
- red colour channel g
- green colour channel b
- blue colour channel "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobdata","title":"Vob_GetMobData
","text":"Vob_GetMobData
Returns the data of the oCMOB object
func C_Mob_Data Vob_GetMobData( var C_Vob mob ) {};\n
mob
- oCMOB object return
- mob data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobdata","title":"Vob_SetMobData
","text":"Vob_SetMobData
Sets the data of the oCMOB object
func void Vob_SetMobData( var C_Vob mob, var C_Mob_Data data ) {};\n
mob
- oCMOB object data
- C_Mob_Data to be set "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobinterdata","title":"Vob_GetMobInterData
","text":"Vob_GetMobInterData
Returns the data of the oCMobInter object
func MobInter_Data Vob_GetMobInterData( var C_Vob mobInter ) {};\n
mobInter
- oCMobInter object return
- MobInter_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobinterdata","title":"Vob_SetMobInterData
","text":"Vob_SetMobInterData
Sets the data of the oCMobInter object
func void Vob_SetMobInterData( var C_Vob mobInter, var C_MobInter_Data data ) {};\n
mobInter
- oCMobInter object data
- MobInter_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobinterdata_1","title":"Vob_GetMobInterData
","text":"Vob_GetMobInterData
Returns the data of the oCMobLockable object
func C_MobLockable_Data Vob_GetMobInterData( var C_Vob mobLock ) {};\n
mobLock
- oCMobLockable object data
- MobInter_Data of the object return
- C_MobLockable_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobinterdata_1","title":"Vob_SetMobInterData
","text":"Vob_SetMobInterData
Sets the data of the oCMobLockable object
func void Vob_SetMobInterData( var C_Vob mobLock, var C_MobLockable_Data data ) {};\n
mobLock
- oCMobLockable object data
- C_MobLockable_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/","title":"WLD - world manipulation functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld---world-manipulation-functions","title":"WLD - world manipulation functions","text":"Functions related to the world.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_changelevel","title":"Wld_ChangeLevel
","text":"Wld_ChangeLevel
Trigger level change.
func void Wld_ChangeLevel( var string world, var string waypoint ) {};\n
world
- name of the world waypoint
- target waypoint "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_findvob","title":"Wld_FindVob
","text":"Wld_FindVob
Return the VOB instance based on its name.
func instance Wld_FindVob( var string vobname ) {};\n
vobname
- name of the vob return
- zCVob pointer "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_playeffectvob","title":"Wld_PlayEffectVob
","text":"Wld_PlayEffectVob
Play a visual effect at specified vob
func void Wld_PlayEffectVob( var string effect,\n var instance pvob,\n var int level,\n var int damage,\n var int damage_type,\n var int damage_speed ) {};\n
effect
- effect name pvob
- zCVob to play the effect at level
- effect level damage
- damage amount damage_type
- damage type damage_speed
- damage interval "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_playeffectat","title":"Wld_PlayEffectAt
","text":"Wld_PlayEffectAt
Play a visual effect at specified world coordinates
func void Wld_PlayEffectAt( var string effect,\n var instance coord,\n var int level,\n var int damage,\n var int damage_type,\n var int damage_speed ) {};\n
effect
- effect name coord
- world coordinates (zVEC3
) to play the effect at level
- effect level damage
- damage amount damage_type
- damage type damage_speed
- damage interval "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_togglerain","title":"Wld_ToggleRain
","text":"Wld_ToggleRain
Turns on the rain
func void Wld_ToggleRain( var float weight, var float time ) {};\n
weight
- the strength of the rain time
- rain duration "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_setweathertype","title":"Wld_SetWeatherType
","text":"Wld_SetWeatherType
Sets the weather type. Types:
0
- snow 1
- rain
func void Wld_SetWeatherType( var int type ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_getweathertype","title":"Wld_GetWeatherType
","text":"Wld_GetWeatherType
Returns the weather type. Types:
0
- snow 1
- rain
func int Wld_GetWeatherType() {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/","title":"Dialogue constants","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dialogue-constants","title":"Dialogue constants","text":"To simplify dialogues, you can define up to 2 auxiliary variables or constants. Values corresponding to the current C_Info
instance will be dynamically written there.
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dia_currentinstance","title":"DIA_CurrentInstance","text":"var int DIA_CurrentInstance\n
Contains the ID of the current C_Info
instance. Can greatly simplify code or make it more reusable. Should be defined in scripts. Example usageInfo_ClearChoices(DIA_CurrentInstance);\nInfo_AddChoice(DIA_CurrentInstance, /*text*/, /*func*/);\nNpc_KnowsInfo(hero, DIA_CurrentInstance); // In this case DIA_CurrentInstance contains the last C_Info instance??\n
Create a wrapper function based on this variablefunc int C_HeroKnowsCurrentInfo()\n{\n return Npc_KnowsInfo(hero, DIA_CurrentInstance);\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dia_currentname","title":"DIA_CurrentName","text":"var string DIA_CurrentName;\n
Contains the name of the current instance of C_Info
. Can be useful for debugging purposes. Should be defined in scripts. Usage scenarios: Hlp_PrintConsole(DIA_CurrentName);\nHlp_PrintConsole(Str_Format(\"%s[%s]\", DIA_CurrentName, self.name);\nHlp_StrCmp(DIA_CurrentName, \"DIA_DiegoOw_Teach\");\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/events/","title":"Event functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/events/#event-functions","title":"Event functions","text":"Event functions are functions sharing the same name. It can be defined multiple times but only once per file. Such functions are useful for implementing callback type functions. Every time an event is called, all instances of the same name will be called. The event is func
with a return type event
. Events are defined globally, meaning they ignore namespace they are in. To call an event from a script, use the external function Hlp_DoEvent(var string funcName)
.
func void GiveXP()\n{\n Hlp_DoEvent(\"OnGiveXP\");\n};\n\nfunc event OnGiveXP()\n{\n // TODO\n // This function can be defined in many files to do different things\n // more appropriate for that file's context and all of them will be\n // called, when function GiveXP (above) is called.\n};\n
Plugin implements two of these event functions
func event GameInit()
- called when entering the main menu on game start func event GameLoop()
- called every frame when a world is loaded Define these in any file in your scripts, they will be automatically called
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/extern/","title":"Extern binding","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/extern/#extern-binding","title":"Extern binding","text":"The extern
binding allows you to secure your code against overriding or undefined symbol. Keyword extern
before declaration means that if object of the same name exists, source object should be used. If not, a new one will be created.
extern instance PC_Hero(C_Npc) \n{\n // TODO\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/","title":"Namespaces","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespaces","title":"Namespaces","text":"zParserExtender also implements namespaces. Namespaces ensure that all symbols inside the namespace are unique.
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#defining-a-namespace","title":"Defining a namespace","text":"To define a namespace the new keyword namespace
is used.
Regular scriptsInjectable scripts namespace zTestNamespace\n{\n var int var01;\n func void func01() { };\n};\n
META\n{\n Namespace = zTestNamespace;\n};\n\nvar int var01;\nfunc void func01() { };\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespace-nesting","title":"Namespace nesting","text":"Namespaces can be nested for finer control. In case of injection, the namespace defined in META is applied to all code inside the script.
To go deeper into the namespaces you use the namespace operator :
. This code shows function with the same name within three different namespaces. The call in GameInit
is made from the global namespace.
namespace zTestNamespace01\n{\n func void func01() { };\n};\n\nnamespace zTestNamespace02\n{\n func void func01() { };\n};\n\nnamespace zTestNamespace03\n{\n namespace zTestNamespace04\n {\n func void func01() { };\n };\n};\n\nfunc event GameInit()\n{\n // In this case, the reference is from global namespace to zTestNamespace\n zTestNamespace01:func01();\n zTestNamespace02:func01();\n zTestNamespace03:zTestNamespace04:func01();\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespace-traversal","title":"Namespace traversal","text":"To go up a namespace tree you use the namespace operator :
without specifying a namespace. Number of operators determines how many levels you go up.
Exiting nested namespacesfunc void func01()\n{\n Hlp_MessageBox(\"#1\");\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#2\");\n };\n\n namespace zTestNamespace02\n {\n func void func01()\n {\n Hlp_MessageBox(\"#3\");\n };\n\n namespace zTestNamespace03\n {\n func void func01()\n {\n Hlp_MessageBox(\"#4\");\n };\n\n func event GameInit()\n {\n :::func01(); // Calls the function 3 levels up\n ::func01(); // Calls the function 2 levels up\n :func01(); // Calls the function 1 level up\n func01(); // Calls the function from the current namespace\n };\n };\n };\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#optional-namespace-specification","title":"Optional namespace specification","text":"There are three cases where the namespace prefix is optional
Shares the same namespaceIf the function is in higher level namespaceIf using
is specified in the META block namespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#1\");\n };\n\n func event GameInit()\n {\n // Function call from the current namespace\n func01();\n };\n};\n
func void func01()\n{\n Hlp_MessageBox(\"#1\");\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#2\");\n };\n\n namespace zTestNamespace02\n {\n func event GameInit()\n {\n // Function call from the global namespace\n func01();\n };\n };\n};\n
META\n{\n using = zTestNamespace01;\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#1\");\n };\n};\n\nfunc event GameInit()\n{\n // Calls the function with the namespace specified in the META block\n func01();\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#global-namespace-and-daedalus-hooking","title":"Global namespace and Daedalus hooking","text":"Namespace can not only be defined to an existing symbol but also to define new ones. Next code example shows how to implement a hook to a global instance.
namespace zTestNamespace01\n{\n const string Var01 = \"New instance name\";\n\n // Hooking the global instance\n instance :ItAr_Pir_L_Addon(C_Item)\n {\n ItAr_Pir_L_Addon_Old();\n name = Var01;\n };\n};\n
To hook an object, both signature and namespace has to match. It is syntactically allowed to hook an instance from a different space. Specify explicitly to which namespace the object will belong. This means that to hook instance ItAr_Pir_L_Addon
from the namespace zTestNamespace01
to a global namespace, you have to refer to the global namespace using the namespace operator :
. Since the function will be defined globally (as every symbol in ZenGin), it will be a part of the zTestNamespace01
which means that all functions will be local to this namespace."},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/","title":"Test-else statements","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/#test-else-statements","title":"Test-else statements","text":"The test-else bind statement can be used to define sections of code to be compiled. If the code is within the boundaries of the inactive test-else branch, it will not be compiled. This operator can take values as input that are converted to logical values. For example, if an object is passed as an argument, the parser will check for its existence. If it is an engine tag, it will return the result of matching the current engine with the tag:
Valid values:
instance name - PC_HERO
, ItMi_Gold
, ... engine tag - G1
, G1A
, G2
, G2A
Steam Overlay activity - Steam
The result can be combined from several arguments. Round brackets ()
can be used to specify priority and expressions support the logical negation operator !
, logical AND &&
and OR ||
.
The operator can be used anywhere in the script file. It is syntactically similar to if else
statement, but curly braces {}
can be omitted for single-line operations. For example:
SteamActivated constant is set only when Steam is activetest Steam var const SteamActivated = 1;\n
Example of a logical expression with an else branchtest SteamActivated && G2A \n{\n // TODO\n}\nelse \n{\n // TODO\n}\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/while/","title":"Native WHILE loop","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/while/#native-while-loop","title":"Native WHILE loop","text":"Just like Ikarus zParserExtender implements a while loop.
var int value; value = 10;\nwhile(value > 0)\n{\n if (value == 8)\n {\n continue;\n };\n\n if (value == 2)\n {\n break;\n };\n};\n
Note
To activate while
it is necessary to set NativeWhile
setting in SystemPack.ini
[ZPARSE_EXTENDER]\nNativeWhile = true\n
Compiled while loop works in vanilla engine without the plugin.
"},{"location":"zengin/scripts/externals/","title":"Externals","text":""},{"location":"zengin/scripts/externals/#externals","title":"Externals","text":"External functions are Daedalus functions (defined in the engine itself), that are used to interface with the engine. Gothic 1 and Gothic 2 implements slightly different set of external functions. There are some external functions, that were used in the course of Gothic's development, but are now obsolete/deprecated because the underlying systems implemented in the engine were either turned off, or broken all together.
"},{"location":"zengin/scripts/externals/doc/","title":"Doc external functions","text":""},{"location":"zengin/scripts/externals/doc/#doc-external-functions","title":"Doc external functions","text":"Doc functions are used to control the document manager. They allow you to fine tune the display of maps, letters and books.
"},{"location":"zengin/scripts/externals/doc/#doc_create","title":"Doc_Create
","text":"Doc_Create
Creates a new instance of the document manager and returns its ID.
func int Doc_Create() {};\n
Return value Returns the ID of the document manager instance.
Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_Create();\n
"},{"location":"zengin/scripts/externals/doc/#doc_createmap","title":"Doc_CreateMap
","text":"Doc_CreateMap
Creates a new instance of the document manager with the arrow showing players position on the map and returns its ID.
func int Doc_CreateMap() {};\n
Return value Returns the ID of the document manager instance.
Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_CreateMap();\n
"},{"location":"zengin/scripts/externals/doc/#doc_setlevel","title":"Doc_SetLevel
","text":"Doc_SetLevel
Set a world level to a map. This maps the texture of the document to the bounding box of the provided level.
func void Doc_SetLevel(var int docID, var string level) {};\n
Parameters
var int docID
- document manager ID var string level
- name of the ZEN file Example
nDocID = Doc_CreateMap();\nDoc_SetLevel(nDocID, \"WORLD.ZEN\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_setlevelcoords","title":"Doc_SetLevelCoords
","text":"Doc_SetLevelCoords
Warning
This function is only available in Gothic 2
Sets the map coordinates. This is used to map smaller portions of the world map to the document map to correctly show players position on the map.
func void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {};\n
Parameters
var int docID
- document manager ID var int left
- left coordinate var int top
- top coordinate var int right
- right coordinate var int bottom
- bottom coordinate Example
Doc_SetLevelCoords(nDocID, -28000, 50500, 95500, -42500);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setfont","title":"Doc_SetFont
","text":"Doc_SetFont
Sets a font
to be used on a page
in a document with docID
. Can be called multiple times to display different lines with different fonts.
func void Doc_SetFont(var int docID, var int page, var string font) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, fonts will be applied to all pages var string font
- font to be used Example
Doc_SetFont(nDocID, -1, \"FONT_10_BOOK.TGA\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_setpages","title":"Doc_SetPages
","text":"Doc_SetPages
Sets the number of pages numOfPages
of the document.
func void Doc_SetPages(var int docID, var int numOfPages) {};\n
Parameters
var int docID
- document manager ID var int numOfPages
- number of pages Example
nDocID = Doc_Create();\nDoc_SetPages(nDocID, 2);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setpage","title":"Doc_SetPage
","text":"Doc_SetPage
Set page
to have texture
as a background with scale
.
func void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, settings are applied to all pages var string texture
- texture of the background var int scale
- scale of the texture, TRUE
to scale the page, FALSE
to not scale Example
Doc_SetPage(nDocID, 0, \"Book_Mage_L.tga\", FALSE);\nDoc_SetPage(nDocID, 1, \"Book_Mage_R.tga\", FALSE);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setmargins","title":"Doc_SetMargins
","text":"Doc_SetMargins
Sets text margins of the page
func void Doc_SetMargins(var int docID,\n var int page,\n var int left,\n var int top,\n var int right,\n var int bottom,\n var int pixels) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, settings are applied to all pages var int left
- left margin var int top
- top margin var int right
- right margin var int bottom
- bottom margin var int pixels
- TRUE
to use pixels, FALSE
to use virtual coordinates Warning
After a thorough examination of this external function in the decompiler, it looks like the function works in pixels only regardless of this parameter.
Example
Doc_SetMargins(nDocID, 0, 275, 20, 30, 20, TRUE);\n
"},{"location":"zengin/scripts/externals/doc/#doc_printline","title":"Doc_PrintLine
","text":"Doc_PrintLine
Prints a line of text
(font is set using Doc_SetFont) onto the document with docID
, onto the page
. Does not split the text into multiple lines if they do not fit onto the page.
func void Doc_PrintLine(var int docID, var int page, var string text) {};\n
Parameters
var int docID
- document manager ID var int page
- page index var string text
- text to be printed Example
Doc_PrintLine(nDocID, 0, \"\"); // insert empty line\nDoc_PrintLine(nDocID, 0, \"The Book\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_printlines","title":"Doc_PrintLines
","text":"Doc_PrintLines
Prints a line of text
(font is set using Doc_SetFont) onto the document with docID
, onto the page
. Splits the text into multiple lines if they do not fit onto the page.
func void Doc_PrintLines(var int docID, var int page, var string text) {};\n
Parameters
var int docID
- document manager ID var int page
- page index var string text
- text to be printed Example
Doc_PrintLines(nDocID, 0, \"The war had been decided. Varant had lost its seaports, vital to army supplies. King Rhobar had not lingered on the battle fields for a long time, but left his generals to deal with the few remaining enemy troops. Varant had only one large force left, commanded by Lukkor, the most capable warlord of the Varant army, who had more than once turned defeat into victory.\");\nDoc_PrintLines(nDocID, 0, \"But now his army was trapped. The situation was hopeless, even though his army greatly outnumbered the enemy. Lee, a war hero from Myrtana, had lured him into this trap. The heavy cavalry had been unable to fight on the thick, swamped ground of the narrow valley. Lee's soldiers had occupied the range of hills surrounding the swamp, and they had struck repeatedly, decimating the army. The desperate sallies his troops had launched had been cut short in pools of blood. He was beaten.\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_show","title":"Doc_Show
","text":"Doc_Show
Display the document using the document manager ID
func void Doc_Show(var int docID) {};\n
Parameters
var int docID
- document manager ID Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_Create();\n\n// ... document configuration\n\nDoc_Show(nDocID);\n
"},{"location":"zengin/scripts/externals/doc/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Creates a new instance of the document manager and returns its ID.\n///\n/// @return Returns the ID of the document manager instance.\nfunc int Doc_Create() {};\n\n/// Create a new instance of the document manager with the arrow showing players position on the map and returns its ID.\n///\n/// @return Returns the ID of the document manager instance.\nfunc int Doc_CreateMap() {};\n\n/// Prints a line of `text` onto the document with `docID`, onto the `page`.\n/// Does not line break\n/// \n/// @param docID document manager ID\n/// @param page page index\n/// @param text text to be printed\nfunc void Doc_PrintLine(var int docID, var int page, var string text) {};\n\n/// Prints a line of `text` onto the document with `docID`, onto the `page`. The `text` is automatically split into multiple lines\n/// \n/// @param docID document manager ID\n/// @param page page index\n/// @param text text to be printed\nfunc void Doc_PrintLines(var int docID, var int page, var string text) {};\n\n/// Sets a `font` to be used on a `page` in a document with `docID`. Can be called multiple times to display different lines with different fonts.\n///\n/// @param docID document manager ID\n/// @param page page index\n/// @param font font to be used\nfunc void Doc_SetFont(var int docID, var int page, var string font) {};\n\n/// Sets the number of pages `numOfPages` of the document.\n///\n/// @param docID document manager ID\n/// @param numOfPages number of pages\nfunc void Doc_SetPages(var int docID, var int numOfPages) {};\n\n/// Set `page` to have `texture` as a background with `scale`. \n///\n/// @param docID document manager ID\n/// @param page page index, if set to `-1`, settings are applied to all pages\n/// @param texture texture of the background\n/// @param scale scale of the texture, if set to 1, there will be no resizing\nfunc void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {};\n\n/// Set a world level to a map.\n///\n/// @param docID document manager ID\n/// @param level name of the ZEN file\nfunc void Doc_SetLevel(var int docID, var string level) {};\n\n/// Sets the map coordinates. \n/// \n/// @param docID document manager ID\n/// @param left left\n/// @param top top\n/// @param right top\n/// @param bottom bottom\nfunc void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {};\n\n/// Sets text margins of the page\n///\n/// @param docID document manager ID\n/// @param page page index, if set to `-1`, settings are applied to all pages\n/// @param left left margin\n/// @param top top margin\n/// @param right right margin\n/// @param bottom bottom margin\n/// @param pixels `TRUE` to use pixels, `FALSE` to use virtual coordinates\nfunc void Doc_SetMargins(var int docID,\n var int page,\n var int left,\n var int top,\n var int right,\n var int bottom,\n var int pixels) {};\n\n/// Display the document using the document manager ID\n///\n/// @param docID document manager ID\nfunc void Doc_Show(var int docID) {};\n\n\n\n/// deprecated\nfunc void Doc_Open (var string Texture) {};\n\n/// deprecated\nfunc void Doc_Font(var string Font) {};\n\n/// deprecated\nfunc void Doc_Print (var string Text) {};\n\n/// deprecated\nfunc void Doc_MapCoordinates(var string s0,\n var float r1,\n var float r2,\n var float r3,\n var float r4,\n var float r5,\n var float r6,\n var float r7,\n var float r8) {};\n
"},{"location":"zengin/scripts/externals/log/","title":"Log external functions","text":""},{"location":"zengin/scripts/externals/log/#log-external-functions","title":"Log external functions","text":"Log externals are used to manipulate players log and to track quest progress.
"},{"location":"zengin/scripts/externals/log/#log_createtopic","title":"Log_CreateTopic
","text":"Log_CreateTopic
Creates a new log topic with the name topicName
under the section logSection
func void Log_CreateTopic(var string topicName, var int logSection) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var int logSection
Indicates in which section to create the topic in. Takes constants LOG_MISSION
, LOG_NOTE
as values "},{"location":"zengin/scripts/externals/log/#log_addentry","title":"Log_AddEntry
","text":"Log_AddEntry
Adds an entry to a log topic with the name topicName
under the section logSection
func void Log_AddEntry(var string topicName, var string entry) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var string entry
Content of the new entry Info
In the engine the Log_AddEntry()
is wrapped in a B_LogEntry()
function. This function also handles printing the \"New Journal Entry\" message to the screen and playing the sound effect.
func void B_LogEntry(var string topic, var string entry)\n{\n PrintDebugNpc(PD_ZS_DETAIL, \"B_LogEntry\"); // Logging\n\n Log_AddEntry(topic, entry);\n\n PrintScreen(NAME_NewLogEntry, -1, _YPOS_MESSAGE_LOGENTRY, \"font_old_10_white.tga\", _TIME_MESSAGE_LOGENTRY);\n Snd_Play(\"LogEntry\");\n};\n
"},{"location":"zengin/scripts/externals/log/#log_settopicstatus","title":"Log_SetTopicStatus
","text":"Log_SetTopicStatus
Changes the status of the topic with the name topicName
func void Log_SetTopicStatus(var string topicName, var int status) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var int status
The status to be set. Takes constants LOG_RUNNING
, LOG_SUCCESS
, LOG_FAILED
, LOG_OBSOLETE
as values "},{"location":"zengin/scripts/externals/log/#zparserextender","title":"zParserExtender","text":"The log external function selection is missing functions to retrieve the status of a log entry. There are only functions to read the log status (as discussed on Inside Gothic). As a result of this the original scriptwriters had to define additional variable to track the log status in the scripts, even though the value is being already tracked by the engine. zParserExtender fixes this by introducing new log external functions.
"},{"location":"zengin/scripts/externals/log/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Creates a new log topic with the name `topicName` under the section `logSection`\n/// \n/// @param topicName unique string used to identify and name the topic\n/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in\nfunc void Log_CreateTopic(var string topicName, var int logSection) {};\n\n/// Creates a new log topic with the name `topicName` under the section `logSection`\n/// \n/// @param topicName unique string used to identify and name the topic\n/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in\nfunc void Log_AddEntry(var string topicName, var string entry) {};\n\n/// Changes the status of the topic with the name `topicName`\n///\n/// @param topicName unique string used to identify and name the topic\n/// @param status [LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE] the status to be set\nfunc void Log_SetTopicStatus(var string topicName, var int status) {};\n
"},{"location":"zengin/scripts/externals/mdl/","title":"MDL functions","text":""},{"location":"zengin/scripts/externals/mdl/#mdl-functions","title":"MDL functions","text":"Functions to tweak animation and other model related settings.
"},{"location":"zengin/scripts/externals/mdl/#mdl_applyoverlaymds","title":"Mdl_ApplyOverlayMDS
","text":"Mdl_ApplyOverlayMDS
Apply an animation overlay with overlay_name
for the specified npc
func void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {};\n
Parameters
var c_npc npc
NPC to apply the overlay to var string overlay_name
Name of the animation overlay "},{"location":"zengin/scripts/externals/mdl/#mdl_applyoverlaymdstimed","title":"Mdl_ApplyOverlayMDSTimed
","text":"Mdl_ApplyOverlayMDSTimed
Apply an animation overlay with overlay_name
for the specified npc
for duration
milliseconds
func void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {};\n
Parameters
var c_npc npc
NPC to apply the overlay to var string overlay_name
Name of the animation overlay var float duration
Overlay duration in milliseconds "},{"location":"zengin/scripts/externals/mdl/#mdl_removeoverlaymds","title":"Mdl_RemoveOverlayMDS
","text":"Mdl_RemoveOverlayMDS
Remove the animation overlay overlay_name
from specified npc
func void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {};\n
Parameters
var c_npc npc
NPC to remove the overlay from var string overlay_name
Name of the animation overlay "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomani","title":"Mdl_ApplyRandomAni
","text":"Mdl_ApplyRandomAni
Assign a random animation ani2
to random animation list of animation ani1
func void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {};\n
Parameters
var c_npc npc
NPC owning the animation var string ani1
The animation to assign random animation to var string ani2
Animation to be assigned "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomanifreq","title":"Mdl_ApplyRandomAniFreq
","text":"Mdl_ApplyRandomAniFreq
Sets the random animation frequency for animation ani1
func void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {};\n
Parameters
var c_npc npc
NPC owning the animation var string ani1
The animation to set the random frequency var float frequency
Number of seconds between random animations Example // Attach T_WOUNDED_TRY animation to the S_WOUNDED animation\nMdl_ApplyRandomAni(self, \"S_WOUNDED\", \"T_WOUNDED_TRY\");\n// Make the random animation attached play every 8 seconds\nMdl_ApplyRandomAniFreq(self, \"S_WOUNDED\", 8);\n
"},{"location":"zengin/scripts/externals/mdl/#mdl_setmodelfatness","title":"Mdl_SetModelFatness
","text":"Mdl_SetModelFatness
Set the procedural model fatness
func void Mdl_SetModelFatness(var c_npc npc, var float fatness) {};\n
Parameters
var c_npc npc
NPC to apply the fatness to var float fatness
Fatness value "},{"location":"zengin/scripts/externals/mdl/#mdl_setmodelscale","title":"Mdl_SetModelScale
","text":"Mdl_SetModelScale
Set model scale per axis
func void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {};\n
Parameters
var c_npc npc
NPC to apply the scale to var float x
Scale along the x-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% var float y
Scale along the y-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% var float z
Scale along the z-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% "},{"location":"zengin/scripts/externals/mdl/#mdl_setvisualbody","title":"Mdl_SetVisualBody
","text":"Mdl_SetVisualBody
Sets up the visual of an NPC
func void Mdl_SetVisualBody(var instance npc,\n var string body_mesh,\n var int body_tex,\n var int skin,\n var string head_mesh,\n var int head_tex,\n var int teeth_tex,\n var int armor_inst ) {};\n
Parameters
var instance npc
NPC to be affected var string body_mesh
Mesh to be used as the body e.g. HUN_BODY_NAKED0
var int body_tex
Body texture assigned to this body mesh var int skin
Body texture variant var string head_mesh
Head mesh var int head_tex
Head texture var int teeth_tex
Teeth texture var int armor_inst
Armor (C_ITEM
instance) to be equipped or -1
for no armor "},{"location":"zengin/scripts/externals/mdl/#mdl_setvisual","title":"Mdl_SetVisual
","text":"Mdl_SetVisual
Set the animation set (also dictates models you can set using the Mdl_SetVisualBody
)
func void Mdl_SetVisual(var instance npc, var string animation_set) {};\n
Parameters
var instance npc
NPC to apply the animation set to var string animation_set
Name of the MDS file that contains the animation set "},{"location":"zengin/scripts/externals/mdl/#mdl_startfaceani","title":"Mdl_StartFaceAni
","text":"Mdl_StartFaceAni
Start a face animation
func void Mdl_StartFaceAni(var c_npc npc,\n var string name,\n var float intensity,\n var float holdtime) {};\n
Parameters
var c_npc npc
NPC to apply the animation to var string name
Animation name var float intensity
Intensity of the animation 0.0 to 1.0 var float holdtime
How long should the animation be held for -2
will use the MMS defined value, '-1' will make the hold time infinite "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomfaceani","title":"Mdl_ApplyRandomFaceAni
","text":"Mdl_ApplyRandomFaceAni
Start a random face animation
func void Mdl_ApplyRandomFaceAni(var c_npc npc,\n var string name,\n var float timemin,\n var float timeminvar,\n var float timemax,\n var float timemaxvar,\n var float probmin) {};\n
Parameters
var c_npc npc
NPC to apply the animation to var string name
Animation name var float timemin
Minimum time after which the ani should be started (in seconds) var float timeminvar
Minimum boundary variation (in seconds) var float timemax
Maximum time after which the ani should be started (in seconds) var float timemaxvar
Maximum boundary variation (in seconds) var float probmin
Probability (0.0 to 1.0) to choose the lower boundary time "},{"location":"zengin/scripts/externals/mdl/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Apply an animation overlay with `overlay_name` for the specified `npc`\n/// \n/// @param npc NPC to apply the overlay to\n/// @param overlay_name name of the animation overlay\nfunc void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {};\n\n/// Apply an animation overlay with `overlay_name` for the specified `npc` for `duration` milliseconds\n///\n/// @param npc NPC to apply the overlay to\n/// @param overlay_name name of the animation overlay\n/// @param duration overlay duration in milliseconds\nfunc void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {};\n\n/// Remove the animation overlay `overlay_name` from specified `npc` \n/// \n/// @param npc NPC to remove the overlay from\n/// @param overlay_name name of the animation overlay\nfunc void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {};\n\n/// Assign a random animation `ani2` to random animation list of animation `ani1`\n///\n/// @param npc NPC owning the animation\n/// @param ani1 the animation to assign random animation to\n/// @param ani2 animation to be assigned\nfunc void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {};\n\n/// Sets the random animation frequency for animation `ani1`\n///\n/// @param npc NPC owning the animation\n/// @param ani1 the animation to set the random frequency\n/// @param frequency number of seconds between random animations\nfunc void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {};\n\n/// Set the procedural model fatness\n///\n/// @param npc NPC to apply the fatness to \n/// @param fatness fatness value\nfunc void Mdl_SetModelFatness(var c_npc npc, var float fatness) {};\n\n/// Set model scale per axis\n///\n/// @param npc NPC to apply the scale to \n/// @param x scale along the x axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \n/// @param y scale along the y axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \n/// @param z scale along the z axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \nfunc void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {};\n\n/// Sets up the visual of an NPC\n///\n/// @param npc NPC to be affected\n/// @param body_mesh mesh to be used as the body e.g. `HUN_BODY_NAKED0`\n/// @param body_tex body texture assigned to this body mesh\n/// @param skin body texture variant\n/// @param head_mesh head mesh\n/// @param head_tex head texture\n/// @param teeth_tex teeth texture\n/// @param armor_inst armor (C_ITEM instance) to be equipped or `-1` for no armor \nfunc void Mdl_SetVisualBody(var instance npc,\n var string body_mesh,\n var int body_tex,\n var int skin,\n var string head_mesh,\n var int head_tex,\n var int teeth_tex,\n var int armor_inst ) {};\n\n/// Set the animation set (also dictates models you can set using the `Mdl_SetVisualBody`)\n///\n/// @param npc NPC to apply the animation set to \n/// @param animation_set name of the MDS file that contains the animation set\nfunc void Mdl_SetVisual(var instance npc, var string animation_set) {};\n\n/// Start a face animation\n///\n/// @param npc NPC to apply the animation to \n/// @param name animation name\n/// @param intensity intensity of the animation 0.0 to 1.0\n/// @param holdtime how long should the animation be held for `-2` will use the MMS defined value, '-1' will make the hold time infinite\nfunc void Mdl_StartFaceAni(var c_npc npc,\n var string name,\n var float intensity,\n var float holdtime) {};\n\n/// Start a random face animation\n///\n/// @param npc NPC to apply the animation to \n/// @param name animation name\n/// @param timemin minimum time after which the ani should be started (in seconds)\n/// @param timeminvar minimum boundary variation (in seconds)\n/// @param timemax maximum time after which the ani should be started (in seconds)\n/// @param timemaxvar maximum boundary variation (in seconds)\n/// @param probmin probability (0.0 to 1.0) to choose the lower boundary time\nfunc void Mdl_ApplyRandomFaceAni(var c_npc npc,\n var string name,\n var float timemin,\n var float timeminvar,\n var float timemax,\n var float timemaxvar,\n var float probmin) {};\n
"},{"location":"zengin/sound/","title":"Sound","text":""},{"location":"zengin/sound/#sound","title":"Sound","text":"ZenGin uses .wav
files for playing Sound Effects and Dubbing.
Info
In-game soundtrack isn't saved in .wav
sound files. See Music.
"},{"location":"zengin/sound/#properties","title":"Properties","text":"Original gothic sound files has following properties:
One channel (Mono) 44100 Hz frequency 32-bit depth "},{"location":"zengin/sound/#sfx","title":"SFX","text":"Sound effects (SFX) are sounds made by monsters, spells, weapons etc. Sound effects are defined in multiple places, in .mds
files as part of the animation EventBlocks, or in the SFX Daedalus scripts. Sounds are located in the _work/Data/Sound/SFX
directory.
"},{"location":"zengin/sound/#speech","title":"Speech","text":"Dubbing for dialogues is located into _work/Data/Sound/Speech
folder. Every single AI_Output
has its own sound file with name defined in the function itself.
For this dialogue line
AI_Output(self,hero,\"Info_Diego_Gamestart_11_00\"); //I'm Diego.\n
the engine will play Info_Diego_Gamestart_11_00.wav
sound file (if it exists)."},{"location":"zengin/sound/tutorials/change_sfx/","title":"Changing Sound Effect","text":""},{"location":"zengin/sound/tutorials/change_sfx/#changing-sound-effect","title":"Changing Sound Effect","text":"This is Gothic VDFS. It is a tool that allows you to pack and unpack files in .VDF and .MOD format.
Let us start with unpacking \"Sound\" file:
In the \"(Viewer)\" tab, in the \"Filename\", go to your Gothic or Gothic II/Data folder and choose \"Sound.VDF\". Create a folder on your desktop or any other easily accessible place on your computer. Name it however you want. Go to \"Root path\" and choose the folder you just created. Press \"Extract volume\" if you want to unpack all sound files. The chosen file should be unpacking right now.
Here are the files we just extracted:
It can oftentimes be tricky to find the sound you are looking for, but we will leave that for later. Let's just see how can we change a sound file in the game now.
Get yourself any short sound file. In order for the sound to work in the game, it needs to be in mono .wav format. A lot of programs let you convert a file such as Audacity, so do just that; Rename your converted file into \"INV_CHANGE.WAV\" and replace it in SFX folder you just extracted; Go back to Gothic VDFS, go to (Builder) tab; In \"Filename\" you choose how do you want your file to be called and its location. I recommend creating separate folder and putting it there. You can also name the file however you want, as long as it has higher time stamp (more on that later) than original Sounds file. To create it as .VDF file, choose \"All file\" in the \"Save file as\" and call it \"Sounds.VDF\"; In \"Root path\" go to and choose \"_WORK\" folder; In the field just below \"Comment\", add a * character and then click on the + next to it; Press \"Build\", and if you did everything right, the folder is being packed back into .VDF file; That's how a successful process looks like:
Now get the file you just created, and put it in your Gothic/Data folder replacing the old one. The file we just replaced changes the sound in main menu and the inventory. If you can hear it, congratulations, you did it!
"},{"location":"zengin/textures/","title":"Textures","text":""},{"location":"zengin/textures/#textures","title":"Textures","text":"Textures are pictures that get projected onto 3D models and on a 2D user interface in the game. ZenGin uses its own texture format .TEX
, that in fact is a container for the texture in one of available formats. This section will discuss how to work with textures in ZenGin.
Note
Technical documentaion of the .TEX
texture format can be found in the ZenKit documentaion.
"},{"location":"zengin/textures/#basics","title":"Basics","text":"All created textures have to be located in the _WORK\\DATA\\TEXTURES\\
directory. The compiled .TEX
files are saved in the _COMPILED\\
subdirectory.
Here are some tips for working with Gothic textures:
Textures must have dimensions that are multiples of 4. Square textures (with some exceptions, like faces or some interface elements) are preferred for easier mipmap generation. It is recommended not to use textures bigger than 4096x4096. Avoid things like _V0
, _A1
etc. in the texture name endings, as suffixes like this are used for multitextures. "},{"location":"zengin/textures/#formats","title":"Formats","text":"When working with textures in ZenGin, it is recommended to use the default texture format if you are unsure about other options. Many of the other formats are either unsupported or buggy in gothic. For transparency, DXT3
format should be used. For pure RGB colors, DXT1
format is recommended.
Tip
Formats like RGBA8888
, BGRA8888
, ARGB8888
and ABGR8888
are properly supported with the zSurface32 patch. Learn more about it in the 32 Bit texture support article.
"},{"location":"zengin/textures/#mipmaps","title":"Mipmaps","text":"Mipmaps are pre-generated versions of textures at different levels of detail. They are used, to improve rendering performance and reduce aliasing artifacts. When engine converts the texture it automatically generates mipmaps. Other tools may handle it differently, so it's better to check it before conversion.
How it works?
If you want to learn more about mipmaps in ZenGin there is a great article by Gothic Reloaded Mod Team.
"},{"location":"zengin/textures/#engine-compilation","title":"Engine compilation","text":"By default, .tga
files with a proper resolution are converted to .TEX
files by the engine, when they appear in the game or a game is started with -convertall
parameter. Also, you can convert textures to .TEX
manually using one of the available tools.
The engine compilation may be affected by keywords in the texture name or directory.
Color depth
Textures are compiled by default with a color depth of 16 bits per pixel and needs 4 bits of memory per pixel. To force the engine to convert textures with a different color depth, you need to add an ending to the name of the texture or directory _16BIT
or _32BIT
. Using 16/32 bit images makes sense when there are visual problems or noise after compression, but they take up more memory.
Example: _WORK\\DATA\\TEXTURES\\SKY\\NOMIP_16BIT\\CLOUDS.TGA
.
nomip
By default, Mipmaps are generated for all textures. However, if the texture path contains the directory nomip
, then a Mipmap will not be created for such a texture. It makes sense to use if you experience visual problems or interference associated with the use of Mipmaps, and also to save memory if the texture is rarely used in the game, or the texture is too small.
Example: _WORK\\DATA\\TEXTURES\\EFFECTS\\NOMIP\\LIGHTNING.TGA
"},{"location":"zengin/textures/#tools","title":"Tools","text":"There are some tools created by the Gothic community, that simplify working with ZenGin textures.
"},{"location":"zengin/textures/#goman","title":"GoMan","text":"Oldest texture tool, created by PyroX. Has a good viewer, but there are already better alternatives.
Download
"},{"location":"zengin/textures/#gotex","title":"GoTex","text":"Simple converter, written by ThielHater. Implements features like custom mipmaps and popular image formats support.
Thread on WoG
GitHub
"},{"location":"zengin/textures/#ztexipy","title":"zTEXiPy","text":"Latest tool, developed by Shoun. Offers batch conversion, an intuitive viewer, and Windows context menu shortcuts.
GitLab
"},{"location":"zengin/textures/32bit_texture/","title":"32 Bit texture support","text":""},{"location":"zengin/textures/32bit_texture/#32-bit-texture-support","title":"32 Bit texture support","text":"By default ZenGin supports only compresed DXT1
and DXT3
textures. zSurface32 patch, created by Gratt improves texture quality by adding proper RGBA8888
, BGRA8888
, ARGB8888
and ABGR8888
format readout and DirectX 32 Bit surface support in ZenGin1 .
To use the patch you must have Union installed. Download the .patch
file here, and put it into system\\
directory.
Warning
It is advised to use BGRA8888
due to performance reasons, as other colorspaces require additional conversion at runtime.
"},{"location":"zengin/textures/32bit_texture/#compilation","title":"Compilation","text":"ZenGin doesn\u2019t natively support the compilation of such textures. This can only be achieved using external programs. The simplest method to create a texture is by utilizing zTEXiPy.
Open your texture in zTEXiPy2 : Choose Save TEX as...
In this window: Uncheck Generate Mipmaps
if your texture is meant to be used as UI. Set the Colorspace
to BGRA8888 (zEnum:3)
or other supported format. Press Save
and check your texture in-game: "},{"location":"zengin/textures/32bit_texture/#but-why","title":"But why?","text":"This type of texture is compatible with any asset, whether it\u2019s armour or a sword. However, the primary application for such high-quality textures is in user interface elements, which make extensive use of gradients and the alpha channel:
BGRA8888 vs DXT3BGRA8888 vs DXT1
This example shows comparison between raw BGRA8888 colorspace and DXT3 (BC2)3 compression. DXT3 shows noticible banding throughout entire texture wherever there's alpha channel, while BGRA8888 has smooth gradient transition.
This example shows comparison between raw BGRA8888 colorspace and DXT1 (BC1)3 compression. DXT1 shows lossy quantization artifacts, while BGRA8888 has none.
Source comparison files are available here.
The drawback of using these textures is their large size, as they contain uncompressed color data. However, this is a small price to pay for the improved quality of the final product.
Note
This article was originally written by Shoun and published on G2O Docs.
To learn more about ZenGin Textures reference click here.\u00a0\u21a9
zTEXiPy supports TGA, DDS, PNG and WEBP by default, so make sure it's one of those formats.\u00a0\u21a9
To learn more about DXTn Algorithm click here.\u00a0\u21a9\u21a9
"},{"location":"zengin/textures/multitextures/","title":"Multitextures","text":""},{"location":"zengin/textures/multitextures/#multitextures","title":"Multitextures","text":"Multitextures are used, for example, to create animation. For example, rippling water is represented by a sequence of textures WATER_A0.TGA
that can be applied to 3D geometry. Also in Gothic, multitextures are used to replace the texture of a character's body.
"},{"location":"zengin/textures/multitextures/#naming-convention","title":"Naming convention","text":"The naming convention for multitextures is as follows:
NAME_[Letter0][Number0]_..[LetterN][NumberN].TGA\n
Example: HUM_HEAD_HAIR1_C0_V0.TGA
In this way, multitextures are interconnected. The format is used exclusively for creating multitextures. Therefore, a name like w_s2_v1.TGA
to name only one texture is not allowed. The engine handles incorrect names, but not quickly.
"},{"location":"zengin/textures/multitextures/#body-textures","title":"Body textures","text":"Multitextures used for the body use two channels:
V - for skin variation C - for skin tone For example, the texture Hum_Body_Naked_V2_C3.tga
describes the body of a person without armor, variant 2, and skin tone 3 (Dark-skinned). Setting up specific character texture variations is determined in the script.
"},{"location":"zengin/tools/","title":"Tools","text":""},{"location":"zengin/tools/#tools","title":"Tools","text":"The community has developed many tools to help with the creation of Gothic mods.
Note
This list is a work in progress.
Daedalus
Daedalus Language Server - a VS Code/VS Codium extension that adds IDE like functionality for Daedalus scripting language Ikarus - A daedalus library for the game Gothic. Exploits the interpreter to allow arbitrary memory access and defines a lot of useful functions for interfacing with the engine. LeGo - A daedalus library for the game Gothic. It contains various packages to support modders. AFSP - Fawkes' & Auronen's script package for Gothic 1 and Gothic 2: Night of the Raven. Ninja - Ninja introduces the possibility of true modular modifications for the video games Gothic and Gothic 2 Night of the Raven. DecDat - Daedalus .DAT
files decompiler. Redefix - OutputUnits compiler and updater. VDFS tools
GothicVDFS - NicoDE's viewer, extractor and builder for .vdf
and .mod
volumes VDFS Tool - Gratt's Union VDFS viewer, extractor, builder, optimizer and ZIP compressor for .vdf
and .mod
volumes World Editors
Spacer - the original world editor for ZenGin, ships with the MDK Union Gothic World Editor - Saturas' world editor, supports new object classes created with Union Gothic World Editor - World editor for vanilla worlds, works with G1, G2 and G2 NotR worlds Spacer.NET - A modernised version of Spacer available as a Gothic Mod. Libraries
ZenKit - A library to load, save and use almost all ZenGin asset files Debugging
zSpy - Debugging tool that displays most of the operations performed by the engine during the Gothic or Spacer running, ships with the MDK. "},{"location":"zengin/tools/gothic_sourcer/","title":"Gothic Sourcer","text":""},{"location":"zengin/tools/gothic_sourcer/#gothic-sourcer","title":"Gothic Sourcer","text":"Gothic Sourcer can be used to do a lot of things.
Todo
TODO
"},{"location":"zengin/tools/zSpy/","title":"zSpy","text":""},{"location":"zengin/tools/zSpy/#zspy","title":"zSpy","text":"zSpy is a debugging tool that displays most of the operations performed by the engine during the Gothic or Spacer running.
Example image of running zSpy
Warning
zSpy must be started before Gothic or the Spacer is started so that the program can find it. Sometimes in Gothic I this has to be done manually, in Gothic II This is done by the GothicStarter_mod.
In order to be able to follow the messages in zSpy, Gothic should be started in the window. The corresponding startup option can be found in GothicStarter (mod). Within Gothic, when Marvin mode is activated, you can switch between window and full-screen mode at any time with the F3
key.
"},{"location":"zengin/tools/zSpy/#log-level","title":"Log Level","text":"With the -zlog#
command in GothicStarter, you can specify how many messages zSpy will output. #
can be a number between -1 and 9. Used for:
-1
- Disable every message (expect fatal errors)
0
- Shows only warnings, faults and fatal errors
1 - 9
- Display more information. Every Information has their priority. If you select 1, the program displays only messages with priority =< 1
, with 5 only priority =< 5
, and with 9, almost everything that Gothic can produce.
For general debugging, recommended value is 5.
"},{"location":"zengin/tools/zSpy/#output","title":"Output","text":"The zSpy issues its reports in the following form:
Time Type Priority User Message ... <filename, #line>\n00:21 Info: 3 B: GOTHIC: Exiting game ... .... <oGameManager.cpp,#617>\n
"},{"location":"zengin/tools/zSpy/#time","title":"Time","text":"Time elapsed since the start of Gothic.exe
"},{"location":"zengin/tools/zSpy/#type","title":"Type","text":"Type of message. The following message types are distinguished:
Fatal:
- Critical error causing application to close.
Fault:
- A simple bug that will not cause the application to stop, but display or performance issues may occur.
Warn:
- A warning of possible consequences. An error that follows soon afterwards could have something to do with it.
Info:
- General information about the progress of the program.
"},{"location":"zengin/tools/zSpy/#priority","title":"Priority","text":"Priority level of the message. Messages with lower priority (higher number) can be disabled. See log level.
"},{"location":"zengin/tools/zSpy/#user","title":"User","text":"User ID - a letter defined by every engine developer to highlight its logs
D
- Dieter U
- Ulf B
- Bert C
- Carsten A
- Andre X
- Kurt "},{"location":"zengin/tools/zSpy/#message","title":"Message","text":"The most important part. A message that contains:
Symbol representing a program module. The names are mostly self-explanatory, so there is no need to type them all (MDL
= 3D models, PAR
= Parser etc.).
The message for the user.
"},{"location":"zengin/tools/zSpy/#configuration","title":"Configuration","text":"In zSpy, you can customize the font and its color depending on the type of message.
In addition, you can configure the logging options:
Filtering various messages (Info, Warn, Fault, Fatal). Auto show/hide zSpy when starting/stopping Gothic. Saving the log file to a separate file. "},{"location":"zengin/tools/zSpy/#console-commands","title":"Console commands","text":"List of console commands related with zSpy.
Note
The list is work in progress. Console commands needs a separate article or section.
"},{"location":"zengin/tools/zSpy/#zerr-level","title":"zerr level
","text":"Sets a level of logging.
zerr level <#>\n
<#>
- max message priority. See log level. "},{"location":"zengin/tools/zSpy/#zerr-searchspy","title":"zerr searchspy
","text":"Links zSpy with Gothic. Useful when you run zSpy when the game is already running.
zerr searchspy\n
"},{"location":"zengin/tools/zSpy/#zerr-authors","title":"zerr authors
","text":"Sets a filter to display only messages of one author.
zerr authors <letter>\n
<letter>
- One of the letters listed here. "},{"location":"zengin/tools/zSpy/#zerr-rem","title":"zerr rem
","text":"Includes a remark into the log.
zerr rem\n
Looks like that: 00:46 Info: 3 B: OPT: Blood-Details: Value=2 .... <oGameManager.cpp,#1302>\n00:57 ---------------\n00:57 ---------------\n01:01 Info: 3 B: GMAN: Leaving Menu-Section .... <oGameManager.cpp,#1537>\n
"},{"location":"zengin/tools/zSpy/#zerr-status","title":"zerr status
","text":"Displays a current status of zSpy in the console.
zerr status\n
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/","title":"Daedalus Language Server","text":""},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#daedalus-language-server","title":"Daedalus Language Server","text":"Daedalus Language Server is a language server for Gothic's scripting language - Daedalus, created by Kirides. However, it is mostly known as VSCode extension, that is in fact named vscode-daedalus.
Warning
This article is focused on the vscode-daedalus extension, but since DLS uses Language Server Protocol it could be implemented into other editors.
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#installation","title":"Installation","text":" Download the.vsix File: Navigate to the latest release page of the vscode-daedalus repository on GitHub. Download the .vsix
file associated with the latest version available.
Open VSCode: Launch Visual Studio Code on your computer.
Access Extensions Tab: Go to the Extensions view in VSCode. You can do this by clicking on the square icon on the sidebar or pressing Ctrl+Shift+X
.
Install from VSIX: Click on the three dot icon located in the top right corner of the Extensions view to open the More Actions menu. Select the \"Install from VSIX...\" option.
Select the.vsix File: A file dialog will appear asking for the path to the .vsix
file you downloaded earlier. Navigate to the location where you saved the .vsix
file, select it, and confirm the selection.
Installation Process: VSCode will then proceed to install the Daedalus Language Server extension from the .vsix
file. Once the installation is complete, you may need to reload VSCode to activate the new extension.
Verify Installation: After reloading, check the Extensions view again to ensure that the Daedalus Language Server extension has been successfully installed.
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#setup","title":"Setup","text":"Before opening a project there are some setting that have to be changed. The table below shows which CodePage you should use according to your language.
CodePage Languages windows-1250 Czech, Polish, Hungarian, Romanian windows-1251 Russian, Ukrainian windows-1252 German, English, French, Italian, Spanish windows-1254 Turkish By default, DLS use windows-1252 encoding, if you want to change you have to edit the settings.json
file.
Open the Command Palette by pressing Ctrl+Shift+P
. Type settings.json
and select the option that appears, usually labeled \"Preferences: Open User Settings (JSON)\". Add the following lines at the end of the file (but before }
), replacing \"Windows-1250\" with the appropriate code page for your language: \"daedalusLanguageServer.fileEncoding\": \"Windows-1250\",\n\"daedalusLanguageServer.srcFileEncoding\": \"Windows-1250\",\n\"[daedalus]\": {\n \"files.encoding\": \"windows1250\"\n}\n
Now if you open a directory that contains e.g. GOTHIC.SRC
file, the extension will parse it and give you all Language Server features.
"},{"location":"zengin/tools/daedalus_tools/decdat/","title":"DecDat","text":""},{"location":"zengin/tools/daedalus_tools/decdat/#decdat","title":"DecDat","text":"DecDat1 is a daedalus scripts decompiler orginaly created by Gottfried. Its goal is to replace Gothic Sourcer's decompiler, which wouldn't been able to decompile scripts with Ikarus and LeGo. However, that doesn't mean that DecDat is able to produce data that can be compiled again. This tool should be used mainly for research and educational purposes. Source code is available here.
"},{"location":"zengin/tools/daedalus_tools/decdat/#instalation","title":"Instalation","text":"The tool is written in Java, allowing it to be executed seamlessly on both Windows and Linux operating systems. To utilize the tool, ensure that Java is installed on your system. We recommend using the Java version available here. Once you have your Java installed, download the latest tool version from GitHub releases page, and run the DecDat.jar
file.
"},{"location":"zengin/tools/daedalus_tools/decdat/#usage","title":"Usage","text":"After opening a DecDat you will see a following window.
To import a .DAT
file click at File -> Open DAT...
select the file encoding, the file itself and optionally OU.BIN
file if you want to parse dialogues.
And that's it, now you have a .DAT
file loaded into app, and you can export the code or search for a specific part.
The original DecDat release post can be found here.\u00a0\u21a9
"},{"location":"zengin/tools/libraries/zenkit/","title":"ZenKit","text":""},{"location":"zengin/tools/libraries/zenkit/#zenkit","title":"ZenKit","text":"ZenKit is a C++-library for loading and saving proprietary ZenGin files and is intended to be a successor to Andre Taulien's ZenLib. ZenKit wrappers for Java and C# are also available in the form of ZenKitCS and ZenKit4J which are also published to NuGet and Maven Central respectively.
ZenKit is used as the file loading and scripting backend for OpenGothic and has recently found adoption in GothicVR.
"},{"location":"zengin/tools/libraries/zenkit/#file-support","title":"File Support","text":"The following file types and operations are supported by ZenKit. Requests to support additional file types are welcome and can be submitted to the GitHub repository.
File Type Extension Load1 Save2 Comment Model Animation .MAN
\u2713 Yes \u2718 No \u2014 Model Hierarchy .MDH
\u2713 Yes \u2713 Yes \u2014 Model Mesh .MDM
\u2713 Yes \u2713 Yes Saving is only partially supported Model .MDL
\u2713 Yes \u2713 Yes Saving is only partially supported Morph Mesh .MMB
\u2713 Yes \u2718 No \u2014 Multi Resolution Mesh .MRM
\u2713 Yes \u2713 Yes \u2014 Mesh .MSH
\u2713 Yes \u2713 Yes Saving is only partially supported Daedalus Script .DAT
\u2713 Yes \u2718 No A VM implementation is available (see Daedalus VM) Texture .TEX
\u2713 Yes ~ Yes There is currently no API to alter image data Font .FNT
\u2713 Yes \u2713 Yes \u2014 ZenGin Archive .ZEN
\u2713 Yes \u2713 Yes \u2014 Text/Cutscenes .BIN
, .CSL
, .DAT
, .LSC
\u2713 Yes \u2713 Yes \u2014 Model Script .MDS
, .MSB
\u2713 Yes \u2718 No \u2014 Virtual File System .VDF
\u2713 Yes \u2713 Yes Allows full integration with the host file system"},{"location":"zengin/tools/libraries/zenkit/#daedalus-vm","title":"Daedalus VM","text":"Along facilities to read and write most resource files you might find in a typical Gothic installation, ZenKit also includes a virtual machine which can execute Daedalus scripts. An extensive API is available to inspect the files, add external handlers and bind Daedalus classes into C++-structs. Bindings for the original classes are available as an extension to ZenKit and available to the C# and Java wrappers natively.
"},{"location":"zengin/tools/libraries/zenkit/#documentation","title":"Documentation","text":"Additional documentation for ZenKit can be found at zk.gothickit.dev.
ZenKit is able to fully load these files\u00a0\u21a9
ZenKit is able to save these files at least partially\u00a0\u21a9
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/","title":"GothicVDFS","text":""},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#gothicvdfs","title":"GothicVDFS","text":"Gothic VDFS is the most popular VDFS tool. It was created by NicoDE and allows viewing, extracting and building .vdf
and .mod
archives.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#download","title":"Download","text":"You can download the tool from NicoDE's website - direct link.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#working-areas","title":"Working areas","text":"GothicVDFS has two working areas one for viewing volumes and one for building volumes.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#viewer","title":"Viewer","text":"This is a blank VDFS viewer:
There are two paths to choose at the top:
Filename - Path of the currently opened .vdf
or .mod
archive Root Path - Path to the place where the files will be extracted When you specify the Filename
the VDFS will load the volume and display some information.
Comment is an information about loaded volume left by the author.
Timestamp is a date and time set by the author. Usually the date coincides with the actual date of the volume's build, but it cannot be taken for granted as it can be easily changed.
Tip
The timestamp defines order of loading volumes into the game. Volumes with the latest timestamp are loaded first.
At the bottom there are three different options for extracting files from archive:
Extract Volume - extract the whole volume to the Root Path Extract Directory - extract only selected folder Extract Selected - extract currently selected files In addition, you can choose if files should keep their structure after extraction or get extracted directly to the Root Path.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#builder","title":"Builder","text":"The second working area is the Builder. It allows you to create new VDF archives.
That's how initial builder looks like:
There are two paths to choose at the top:
Filename - Path of the new .vdf
or .mod
archive Root Path - Path to the Gothic directory In the middle there are three areas in which you can specify archive files.
File(mask)(s) to search for - list of file masks to load in VDF archive e.g. _WORK/Data/Anims/_compiled/*
File(mask)(s) to exclude - list of file masks to exclude File(mask)(s) to include - list of file masks to include At the bottom there are three buttons:
Open Script - open a .vm
script file with VDF configuration Save Script - save current VDF configuration to a .vm
script file Build Volume - build the VDF archive with current configuration Example build configuration could look like this:
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#cli-interface","title":"CLI Interface","text":"CLI interface is very simple and allows building and extracting VDF archives without GUI. That's good for automation and scripting.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#build-vdf-from-script","title":"Build VDF from script","text":"GothicVDFS.exe /B script.vm\n
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#extract-vdf-to-directory","title":"Extract VDF to directory","text":"GothicVDFS.exe /X MySuperMod.mod ./extract_here\n
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#script-reference","title":"Script Reference","text":"GothicVDFS uses simple script language to define VDF archives. The script is a simple text file with .vm
extension. The script is divided into sections, each section is marked by a header in square brackets. The script must contain at least [BEGINVDF]
and [ENDVDF]
sections.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#beginvdf","title":"[BEGINVDF]
","text":"Marks the start of script and contains VDF properties.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#comment","title":"Comment
","text":"Comment of VDF archive. Equivalent of \"Comment\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#basedir","title":"BaseDir
","text":"Root path of local files (relative to working directory). Equivalent of \"Root Path\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#vdfname","title":"VDFName
","text":"Name of final VDF file (relative to working directory). Equivalent of \"Filename\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#files","title":"[FILES]
","text":"List of file masks to load in VDF archive (relative to BaseDir). Equivalent of \"File(mask)(s) to search for\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#exclude","title":"[EXCLUDE]
","text":"List of file masks to exclude. Equivalent of \"File(mask)(s) to exclude\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#include","title":"[INCLUDE]
","text":"List of file masks to include. Equivalent of \"File(mask)(s) to include\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#endvdf","title":"[ENDVDF]
","text":"Marks end of file.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#example-script","title":"Example script","text":"example.vm[BEGINVDF]\nComment=Some VDFS archive\nBaseDir=.\nVDFName=SuperMod.mod\n[FILES]\n_work/Data/Anims/_compiled/*\n_work/Data/Meshes/_compiled/*\n_work/Data/Scripts/_compiled/*\n[EXCLUDE]\n*.wav\n[INCLUDE]\nthis_is_fine.wav\n[ENDVDF]\n
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/","title":"VDFS Tool","text":""},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#vdfs-tool","title":"VDFS Tool","text":"VDFS Tool1 is a new program that supports new features introduced to VDFS by the Union team. Like ZIP compression or drag and drop support.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#download","title":"Download","text":"You can download the tool using the Resource Manager or directly from the post on WoP.ru - VDFS Tool.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#features","title":"Features","text":""},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#volume-compression","title":"Volume compression","text":"Volumes are compressed using the classic zip algorithm. The zlib library for buffer compression and decompression was taken as a basis. In order for the game to decompress the volume in real time without loss of performance, a special interface Gratt-5r2/ZippedStream was implemented and built into vdfs32g
. The essence of the interface is that it allows you to pack and read files in blocks of a given size and keep unpacked data in memory in a specific range.
Warning
Compresed .mod
and .vdf
archives works only with Union installed.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#volume-optimization","title":"Volume optimization","text":"Optimization refers to the procedure of identifying files with the same content and combining them under a common data source.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#file-explorer-interface","title":"File Explorer Interface","text":"The program interface has a set of standard file explorer operations - copying, pasting, renaming, searching, etc.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#dragdrop","title":"Drag&Drop","text":"The function allows you to drag files into the program, as well as pull them out of it. For this function to work correctly, user (administrator) rights must match for the program and Explorer.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#updating-a-volume-in-1-click","title":"Updating a volume in 1 click","text":"The program analyzes shared files in the volume and in the game directories (Ctrl + U). If there are physical copies, when you save the volume, updated files will be written to it.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#opening-files-directly-from-a-volume","title":"Opening files directly from a volume","text":"To avoid wasting time unpacking the volume, double-click on the file of interest, after which it will be opened.
This is mostly a translation of the orginal release post.\u00a0\u21a9
"},{"location":"zengin/union/","title":"Union","text":""},{"location":"zengin/union/#union","title":"Union","text":"Union is a system to patch and extend Gothic's engine the ZenGin. It allows you to load .dll
files - ZenGin extensions created using the Gothic/Union SDK and .patch
files - files designed to patch the game's executable. The Union installer also contains the SystemPack a collection of bug fixes and engine edits that improve performance.
"},{"location":"zengin/union/#plug-ins","title":"Plug-ins","text":"Union plugins are shipped in the form of a .dll
library. This library contains the compiled C++ code with the Union SDK and an embedded .patch
file.
"},{"location":"zengin/union/#union-sdk--gothic-api","title":"Union SDK & Gothic API","text":"Union software development kit is a collection of tools and the Gothic API that allow you to create Union plugins and alter the engine's behavior. Gothic API is a set of 4 interfaces (each for one different ZenGin version) that allow you to interface with the engine, access the engine objects, change their behavior and introduce new classes and functionality.
"},{"location":"zengin/union/#patch-file-format","title":"PATCH file format","text":"The .patch
file contains one or more small programs that are designed to change the engine code (game executable). This is usually done to fix bugs. Union plug-ins contain an embedded .patch
file and this file usually contains changes to the binary necessary for the proper function of the plug-in.
"},{"location":"zengin/union/patch/","title":"Patch files","text":""},{"location":"zengin/union/patch/#patch-files","title":"Patch files","text":".patch
files are scripts that are used to change memory values or committing some actions when starting the engine. Files patches are launched from any directories monitored by the file system (System, Saves, _Work and any others at the request of the engine). The launch is performed both from physical directories and from VDF & MOD. If physical and virtual directories contain identical patches with identical paths, physical copies will have read priority.
Info
An additional [patch name] .MAP file can be created. This happens when the patch file has at least one patch marked 'static' (see the description of the patch format for more details). This file allows you to immediately download all previously made changes to process memory, skipping re-parsing of static blocks. By default, the file cannot be seen through standard files explorer. To make the file hidden, but visible, set the value SystemPack.ini -> ShowHiddenFiles = true.
Description of the patch format
"},{"location":"zengin/union/plugins/","title":"Union Plugins","text":""},{"location":"zengin/union/plugins/#union-plugins","title":"Union Plugins","text":"Plugins are libraries dynamically loaded via Union. They can be used to modify the behavior of the game, add new features, and fix bugs. Plugins are written in C++ and compiled into DLL files. The Union SDK and Gothic API provide a set of functions and classes that can be used to create plugins.
Warning
The plugin system is also a potential source of errors. If the plugin is written incorrectly, it can cause the game to crash or behave incorrectly. Therefore, when using plugins, you should be careful and follow the instructions of the plugin authors.
"},{"location":"zengin/union/plugins/#loading","title":"Loading","text":"Loading can be done both Physically and from VDF or MOD volumes. There are three options for loading libraries:
"},{"location":"zengin/union/plugins/#systempackini","title":"Systempack.ini","text":"The classic way is to specify the list of library names in SystemPack.ini -> PluginList separated by commas. Also through this parameter you can control the priority of launching plugins:
If you specify two asterisks (plugin.dll**) at the end of the library name, then it will be loaded earlier than the Virtual file system. But in this case it cannot be loaded from VDF or MOD volume.
If you specify one asterisk (plugin.dll*) at the end of the library name, then it will be launched immediately after the Virtual file system. At this stage the library can be loaded from VDF or MOD volume.
If the name of the library is specified without changes (plugin.dll), then it will be loaded simultaneously with the game. At this stage libraries have the ability to use global instances of Gothic classes.
"},{"location":"zengin/union/plugins/#autorun","title":"Autorun","text":"If the library is located in the Physical Directory System/Autorun
or in the Virtual Directory */Autorun
, then the library will be loaded along with the engine, as in step 1.III. In current versions of Union, the order of loading plugins from this folder is determined by the dependencies of the libraries on each other. This means that if one plugin imports symbols from another, then the Exporting will be loaded first, and then the Importing.
"},{"location":"zengin/union/plugins/#patch-file","title":"Patch File","text":"The patch files start automatically. This means that plugins can also run patches along with them. There are two script functions: LoadLibrary(\"plugin.dll\")
and LoadPlugins(\"plugin1.dll\", ..., \"pluginN.dll\")
.
"},{"location":"zengin/union/plugins/zSplitDialogs/","title":"zSplitDialogs","text":""},{"location":"zengin/union/plugins/zSplitDialogs/#zsplitdialogs","title":"zSplitDialogs","text":"Union plugin created by Top Layer, which gives possibility to extract dialogues from compiled scripts. That could be useful for creating dubbing, especially if you want to know which dialogues are voiced and which are not.
Download
Source code
"},{"location":"zengin/union/plugins/zSplitDialogs/#usage","title":"Usage","text":" Install Union 1.0l+ (zParserExtender is needed - it is inside Union since 1.0l version) Make sure zParserExtender is enabled in SystemPack.ini
[CORE]\nParserExtenderAlwaysOn = true\n
Put zSplitDialogs.vdf
into Data\\
directory Start game After this steps .txt
file with dialogues will be created in Dialogs\\
directory.
Example of a plugin output
"},{"location":"zengin/union/plugins/zSplitDialogs/#configuration","title":"Configuration","text":"At first run, in gothic.ini
will be created following section:
[ZSPLITDIALOGS]\nUnvoicedOnly=0\n
You can change value to 1
to receive only unvoiced subtitles.
"},{"location":"zengin/union/plugins/zbassmusic/","title":"zBassMusic","text":""},{"location":"zengin/union/plugins/zbassmusic/#zbassmusic","title":"zBassMusic","text":"zBassMusic is a modern music system for Gothic games based on ZenGin. It replaces the original DirectMusic system with a custom engine built on top of BASS Library to provide easier workflow for composers and additional functions for the perfect soundtrack design.
Info
The plugin has its very own docuentation site, if you are interested in including zBassMusic into your project see the detailed User Guide.
Contacts Authors Silver Ore Team - tehe GitHub zBassMusic Discord Gothic Modding Community server"},{"location":"zengin/union/plugins/zbassmusic/#features","title":"Features","text":" Direct playback of common audio formats (WAV, OGG, MP3) instead of DirectMusic proprietary formats Out-of-the-box support for existing music theme definitions (just change the audio file) Alternative scheduling & transition systems to support smooth cross-fades between themes Loading of music files from VDF volumes (DirectMusic required physical files) Scriptable interface for controlling the system from Deadalus scripts Backward compatibility with original .sgt
music (it's redirected to the DirectMusic system) "},{"location":"zengin/union/plugins/zgamepad/","title":"zGamePad","text":""},{"location":"zengin/union/plugins/zgamepad/#zgamepad","title":"zGamePad","text":"zGamePad plugin adds gamepad support for ZenGin games.
Important
Visit the excellent original GitHub wiki page.
Contacts Author Gratt GitHub zGamePad Forum zGamePad"},{"location":"zengin/union/plugins/zgamepad/#gamepad-support","title":"Gamepad support","text":" All xinput compatible (including emulators) Xbox controller family Dualshock 4 Dualsense Nintendo Switch Joy-Cons Nintendo Switch Pro Controller "},{"location":"zengin/union/plugins/zgamepad/#features","title":"Features","text":" Natural Movements Intuitiveness and smoothness of movement controls is the main goal of this plugin. Touch the world of Gothic with your hands. Interactive hints Interactive hints will help you in mastering the controls. You can always customize their appearance or disable them. Quick access The plugin has two quick access rings - **weapons and items. Use them to always have access to your items. Automatic save naming Sit comfortably. You do not have to reach for your keyboard, because the plugin itself will give a name to your saves. Saves rotation The best alternative to quicksaves for gamepad controls. Vibration response Immerse yourself in the game even more. Vibration will allow you to feel your character and everything that happens in the world. Target locking The plugin will always help you win. Keeping the enemy in focus will allow you to fight much more effectively. Stuck protection Oops! If you get stuck, hold both analogue sticks for a few seconds and the character will reset. "},{"location":"zengin/union/plugins/zgamepad/controls/","title":"Gamepad controls","text":""},{"location":"zengin/union/plugins/zgamepad/controls/#gamepad-controls","title":"Gamepad controls","text":"The zGamePad plugin comes with a default control scheme, but it is possible to create your own. The plugin will search for any file with the .gamepad.overlay
extension placed in Gothic/System
directory or in any of the loaded .mod
and .vdf
archives.
"},{"location":"zengin/union/plugins/zgamepad/controls/#control-file-syntax","title":"Control file syntax","text":"Gamepad controls are set using the .gamepad
configuration file. This file encodes the controls for different actions in the game and the hint string in multiple languages.
Warning
The .gamepad
file must be encoded in Unicode or UTF-8 to accommodate the multilingual hint strings.
"},{"location":"zengin/union/plugins/zgamepad/controls/#regions","title":"Regions","text":"The format supports code blocks specified by the #region
and #endregion
keywords. These regions do not have any syntactical meaning, they only offer a convenient way to collapse sections of the code in editors with the syntax highlighting capabilities such as Notepad++
Regions#region strings\n // TODO\n#endregion\n\n#region fight scheme\n // TODO\n#endregion\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#comments","title":"Comments","text":"Comments are useful for quick information or just to disable some old code that might come in handy later. The .gamepad
file syntax supports C++ line comments using two forward slashes //
.
Warning
Comments can only be used at the start of any given line!
Comments// this is a comment\nKeyRecord // this is NOT a comment\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#strings","title":"Strings","text":"Strings are used for interactive hints. They should be defined at the top of the file. To define a string, use the keyword String
. Strings have the following format:
Multilang string syntaxString [id]\n [langTag] [text]\n [langTag] [text]\n [langTag] [text]\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#example","title":"Example","text":"String interact\n Rus \"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c\"\n Eng \"Interact\"\n Pol \"Interakcja\"\n Deu \"Interagieren\"\n\nString remove_weapon\n Rus \"\u0423\u0431\u0440\u0430\u0442\u044c \u043e\u0440\u0443\u0436\u0438\u0435\"\n Eng \"Remove weapon\"\n Pol \"Chowanie broni\"\n Deu \"Waffe entfernen\"\n
The string name
must be unique and is used to reference the string while defining hints. The language tag matches the language in SystemPack.ini
. If the file does not contain the user's language, English will be taken by default. If there is no English, then the first one."},{"location":"zengin/union/plugins/zgamepad/controls/#control-bindings","title":"Control bindings","text":"A binding is a description of an event that includes emulation object and conditions. Hints are part of the binding. The general structure of the bind starts with the keyword KeyRecord
and has the following format:
Control bindingKeyRecord [modifier]\n Id [key name]\n Combination [gamepad keys]\n Emulation [engine logical and absolute keys]\n Condition [engine logical, absolute keys or logical functions]\n Help [name of the hint string]\n
Tip
All operators are optional! This means that if a binding should only show a hint, it doesn't have to contain Combination.
"},{"location":"zengin/union/plugins/zgamepad/controls/#example_1","title":"Example","text":"Control binding examplesKeyRecord\n Id StopUsingPicklock\n Combination JOY_B\n Emulation KEY_DOWN\n Condition Cond_InterfaceIsOpen, Cond_UsesPicklock, !JOY_B\n\nKeyRecord Toggled\n Id ReturnToHumanForm\n Combination JOY_A\n Emulation KEY_RETURN\n Condition Cond_InTransformation\n Help end_transform\n\nKeyRecord\n Id QuickRingSelectSlot\n Combination JOY_RSTICK_FULL\n Condition !Cond_InventoryIsOpen, Cond_IsOverlayTop\n Help focus_item\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#controls-override","title":"Controls override","text":"If you want to change or remove bindings from another controls file, use the KeyDisable
keyword. Default controls file
Controls override syntaxKeyDisable [fileName].[Id]\n
Where fileName
is the name of the controls file without extension and id
is a key of the binding."},{"location":"zengin/union/plugins/zgamepad/controls/#example_2","title":"Example","text":"Controls override example// remove key from the main controls file\nKeyDisable Controls.ArrowDown\n\n// create new key based on the same buttons\nKeyRecord Toggled\n Id ArrowDownNew\n Combination JOY_DOWN\n Emulation GAME_DOWN\n
"},{"location":"zengin/union/plugins/zgamepad/keys_engine_absolute/","title":"Engine absolute keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_engine_absolute/#engine-absolute-keys","title":"Engine absolute keys","text":"Absolute keys are the physical keys on your keyboard.
MOUSE_DX\nMOUSE_DY\nMOUSE_UP\nMOUSE_DOWN\nMOUSE_LEFT\nMOUSE_RIGHT\nMOUSE_WHEELUP\nMOUSE_WHEELDOWN\nMOUSE_BUTTONLEFT\nMOUSE_BUTTONRIGHT\nMOUSE_BUTTONMID\nMOUSE_XBUTTON1\nMOUSE_XBUTTON2\nMOUSE_XBUTTON3\nMOUSE_XBUTTON4\nMOUSE_XBUTTON5\nKEY_ESCAPE\nKEY_1\nKEY_2\nKEY_3\nKEY_4\nKEY_5\nKEY_6\nKEY_7\nKEY_8\nKEY_9\nKEY_0\nKEY_MINUS\nKEY_EQUALS\nKEY_BACK\nKEY_TAB\nKEY_Q\nKEY_W\nKEY_E\nKEY_R\nKEY_T\nKEY_Y\nKEY_U\nKEY_I\nKEY_O\nKEY_P\nKEY_LBRACKET\nKEY_RBRACKET\nKEY_RETURN\nKEY_LCONTROL\nKEY_A\nKEY_S\nKEY_D\nKEY_F\nKEY_G\nKEY_H\nKEY_J\nKEY_K\nKEY_L\nKEY_SEMICOLON\nKEY_APOSTROPHE\nKEY_GRAVE\nKEY_LSHIFT\nKEY_BACKSLASH\nKEY_Z\nKEY_X\nKEY_C\nKEY_V\nKEY_B\nKEY_N\nKEY_M\nKEY_COMMA\nKEY_PERIOD\nKEY_SLASH\nKEY_RSHIFT\nKEY_MULTIPLY\nKEY_LMENU\nKEY_SPACE\nKEY_CAPITAL\nKEY_F1\nKEY_F2\nKEY_F3\nKEY_F4\nKEY_F5\nKEY_F6\nKEY_F7\nKEY_F8\nKEY_F9\nKEY_F10\nKEY_NUMLOCK\nKEY_SCROLL\nKEY_NUMPAD7\nKEY_NUMPAD8\nKEY_NUMPAD9\nKEY_SUBTRACT\nKEY_NUMPAD4\nKEY_NUMPAD5\nKEY_NUMPAD6\nKEY_ADD\nKEY_NUMPAD1\nKEY_NUMPAD2\nKEY_NUMPAD3\nKEY_NUMPAD0\nKEY_DECIMAL\nKEY_OEM_102\nKEY_F11\nKEY_F12\nKEY_F13\nKEY_F14\nKEY_F15\nKEY_KANA\nKEY_ABNT_C1\nKEY_CONVERT\nKEY_NOCONVERT\nKEY_YEN\nKEY_ABNT_C2\nKEY_NUMPADEQUALS\nKEY_PREVTRACK\nKEY_AT\nKEY_COLON\nKEY_UNDERLINE\nKEY_KANJI\nKEY_STOP\nKEY_AX\nKEY_UNLABELED\nKEY_NEXTTRACK\nKEY_NUMPADENTER\nKEY_RCONTROL\nKEY_MUTE\nKEY_CALCULATOR\nKEY_PLAYPAUSE\nKEY_MEDIASTOP\nKEY_VOLUMEDOWN\nKEY_VOLUMEUP\nKEY_WEBHOME\nKEY_NUMPADCOMMA\nKEY_DIVIDE\nKEY_SYSRQ\nKEY_RMENU\nKEY_PAUSE\nKEY_HOME\nKEY_UP\nKEY_PRIOR\nKEY_LEFT\nKEY_RIGHT\nKEY_END\nKEY_DOWN\nKEY_NEXT\nKEY_INSERT\nKEY_DELETE\nKEY_LWIN\nKEY_RWIN\nKEY_APPS\nKEY_POWER\nKEY_SLEEP\nKEY_WAKE\nKEY_WEBSEARCH\nKEY_WEBFAVORITES\nKEY_WEBREFRESH\nKEY_WEBSTOP\nKEY_WEBFORWARD\nKEY_WEBBACK\nKEY_MYCOMPUTER\nKEY_MAIL\nKEY_MEDIASELECT\nKEY_BACKSPACE\nKEY_NUMPADSTAR\nKEY_LALT\nKEY_CAPSLOCK\nKEY_NUMPADMINUS\nKEY_NUMPADPLUS\nKEY_NUMPADPERIOD\nKEY_NUMPADSLASH\nKEY_RALT\nKEY_UPARROW\nKEY_PGUP\nKEY_LEFTARROW\nKEY_RIGHTARROW\nKEY_DOWNARROW\nKEY_PGDN\n
"},{"location":"zengin/union/plugins/zgamepad/keys_engine_logical/","title":"Engine logical keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_engine_logical/#engine-logical-keys","title":"Engine logical keys","text":"Logical keys are the keys you set in keyboard settings in the game menu. These can fill multiple roles in different situations and the gamepad controls can be set to emulate these logical keys.
GAME_LEFT\nGAME_RIGHT\nGAME_UP\nGAME_DOWN\nGAME_ACTION\nGAME_SLOW\nGAME_ACTION2\nGAME_WEAPON\nGAME_SMOVE\nGAME_SMOVE2\nGAME_SHIFT\nGAME_END\nGAME_INVENTORY\nGAME_LOOK\nGAME_SNEAK\nGAME_STRAFELEFT\nGAME_STRAFERIGHT\nGAME_SCREEN_STATUS\nGAME_SCREEN_LOG\nGAME_SCREEN_MAP\nGAME_LOOK_FP\nGAME_LOCK_TARGET\nGAME_PARADE\nGAME_ACTIONLEFT\nGAME_ACTIONRIGHT\nGAME_LAME_POTION\nGAME_LAME_HEAL\n
"},{"location":"zengin/union/plugins/zgamepad/keys_gamepad/","title":"Gamepad keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_gamepad/#gamepad-keys","title":"Gamepad keys","text":"In order to set gamepad keys, you have to know the key codes as they are listed below.
JOY_UP\nJOY_DOWN\nJOY_LEFT\nJOY_RIGHT\nJOY_MENU\nJOY_VIEW\nJOY_LSTICK\nJOY_RSTICK\nJOY_LB\nJOY_RB\nJOY_A\nJOY_B\nJOY_X\nJOY_Y\nJOY_LSTICK_LOWUP\nJOY_LSTICK_UP\nJOY_LSTICK_DOWN\nJOY_LSTICK_LEFT\nJOY_LSTICK_RIGHT\nJOY_RT\nJOY_LT\nJOY_DPAD\nJOY_UPDOWN\nJOY_LEFTRIGHT\nJOY_LSTICK_FULL\nJOY_RSTICK_FULL\n
"},{"location":"zengin/union/plugins/zgamepad/logical_functions/","title":"Logical function names","text":""},{"location":"zengin/union/plugins/zgamepad/logical_functions/#logical-function-names","title":"Logical function names","text":"Conditions for when to show or allow the control binding to work are specified using these logic functions. They describe different useful states of the game or user interface, allowing the user to set when will a certain control work.
Cond_FightMode - player is in the fight mode\nCond_FightModeMelee - player is in the melee fight mode\nCond_FightModeRange - player is in the ranged fight mode\nCond_FightModeMagic - player is in the magical fight mode\nCond_CanShoot - player is in the aim mode and can shoot now\nCond_CanSneaking - player is sneaking now\nCond_Diving - player is diving now\nCond_HasFocusVob - player has a focus vob\nCond_HasFocusNpc - player has a focus npc\nCond_OnChooseWeapon - weapon selection is active\nCond_InventoryIsOpen - inventory is open\nCond_InTransformation - player is transformed\nCond_VideoIsOpen - video is playing\nCond_CanLockTarget - player in the fight mode now and can lock the focus vob\nCond_G1 - this engine is a Gothic 1 (or sequel)\nCond_G2 - this engine is a Gothic 2 NoTR (or classic)\nCond_IsDialogTop - dialog window is open on the top\nCond_IsDocumentTop - document object is open on the top\nCond_IsOverlayTop - gamepad overlay object is open on the top\nCond_IsMenuTop - game menu is open on the top\nCond_OnSpellBook - magic selection ring is active\nCond_IsPlayerTalking - player is talking to someone\nCond_InterfaceIsOpen - open any interface element\nCond_HasLeftContainer - the left container is open (chest, plunder, trader)\nCond_UsesPicklock - player is picking a lock now\nCond_IsOnTrade - player is trading\nCond_IsOverlayTop - gamepad overlay object is open on the top\nCond_IsMenuTop - game menu is open on the top\n
"},{"location":"zengin/union/sdk/","title":"Union SDK","text":""},{"location":"zengin/union/sdk/#union-sdk","title":"Union SDK","text":"Union SDK is a software development kit for making Union plugins that directly interact with Gothic engines. It contains a project template for Visual Studio IDE, a C++ library for hooking into a Gothic executable, and Gothic API with methods' addresses for the engines of Gothic I, Gothic II, Gothic II NotR, and also for the not released Gothic Sequel.
Working with Union SDK requires at least basic knowledge of C++ programming. Knowledge of the x86 (32-bit) architecture, dynamically linked libraries, and reverse engineering is also welcomed as we need to understand what the Gothic engine does under the hood to use it effectively.
"},{"location":"zengin/union/sdk/#requirements","title":"Requirements","text":"Union SDK requires Visual Studio IDE, NET Framework 4.7.2, and Visual C++ 2010 libraries. They are available on Microsoft websites:
Visual Studio - https://visualstudio.microsoft.com/vs/ NET Framework 4.7.2 - https://dotnet.microsoft.com/download/dotnet-framework/net472 Visual C++ 2010 - https://www.microsoft.com/download/details.aspx?id=26999 "},{"location":"zengin/union/sdk/#resource-manager","title":"Resource Manager","text":"The official installation of Union SDK is provided through Resource Manager. After the installation, Visual Studio will have a new project template \"Union Plugin 1.0\" that creates a basic Union plugin project.
"},{"location":"zengin/union/sdk/events/","title":"Game Events","text":""},{"location":"zengin/union/sdk/events/#game-events","title":"Game Events","text":"Union defines several Game Events that are dispatched when a specific event occurs in-game. Handlers are defined in Plugin.cpp
and we can use them to execute our code during specific moments of the application lifetime.
"},{"location":"zengin/union/sdk/events/#events","title":"Events","text":""},{"location":"zengin/union/sdk/events/#initialization","title":"Initialization","text":""},{"location":"zengin/union/sdk/events/#game_entry","title":"Game_Entry","text":"Executes at the entry point of the Gothic executable. During this time the engine classes are not yet initialized, so using them may cause an access violation. The entry point be used to execute some logic before Gothic loads itself.
void Game_Entry() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_defineexternals","title":"Game_DefineExternals","text":"Executes before the Daedalus parser starts loading scripts. It's meant to define custom external functions.
void Game_DefineExternals() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_init","title":"Game_Init","text":"Executes right after DAT files are loaded and just before the main menu shows up.
void Game_Init() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#level-change","title":"Level Change","text":""},{"location":"zengin/union/sdk/events/#game_loadbegin","title":"Game_LoadBegin","text":"Executes when we initiate a level change by one of the possible actions. The default plugin template uses a common LoadBegin()
function to handle all events but we also can write different logic for different cases.
void LoadBegin() {\n\n}\n\n// When player clicks \"New Game\"\nvoid Game_LoadBegin_NewGame() {\n LoadBegin();\n}\n\n// When player loads a saved game\nvoid Game_LoadBegin_SaveGame() {\n LoadBegin();\n}\n\n// When player changes ZEN by a trigger\nvoid Game_LoadBegin_ChangeLevel() {\n LoadBegin();\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadend","title":"Game_LoadEnd","text":"Executes when the level loading finishes. The default plugin template uses a common LoadEnd()
function to handle all events but we also can write different logic for different cases.
void LoadEnd() {\n\n}\n\n// When player clicks \"New Game\"\nvoid Game_LoadEnd_NewGame() {\n LoadEnd();\n}\n\n// When player loads a saved game\nvoid Game_LoadEnd_SaveGame() {\n LoadEnd();\n}\n\n// When player changes ZEN by a trigger\nvoid Game_LoadEnd_ChangeLevel() {\n LoadEnd();\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadbegin_trigger","title":"Game_LoadBegin_Trigger","text":"Executes when the player enters a trigger that initiates ZEN change.
void Game_LoadBegin_Trigger() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadend_trigger","title":"Game_LoadEnd_Trigger","text":"Executes after the player has entered a trigger that initiates ZEN change.
void Game_LoadEnd_Trigger() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_applyoptions","title":"Game_ApplyOptions","text":"Executes after Game_LoadEnd
, when we save the game, and also when we exit the game. It's meant to be used to apply options from INI files.
void Game_ApplyOptions() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game-loop","title":"Game Loop","text":""},{"location":"zengin/union/sdk/events/#game_preloop","title":"Game_PreLoop","text":"Executes at the start of every frame.
void Game_PreLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_loop","title":"Game_Loop","text":"Executes at every frame.
void Game_Loop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_postloop","title":"Game_PostLoop","text":"Executes at the end of every frame.
void Game_PostLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_menuloop","title":"Game_MenuLoop","text":"Executes at every frame when the game menu is active.
void Game_MenuLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_savebegin","title":"Game_SaveBegin","text":"Executes when the player started saving a game.
void Game_SaveBegin() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_saveend","title":"Game_SaveEnd","text":"Executes when the game save finishes.
void Game_SaveEnd() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_pause","title":"Game_Pause","text":"Executes when the player opens the in-game menu.
void Game_Pause() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_unpause","title":"Game_Unpause","text":"Executes when the player leaves the in-game menu and also when the player loads a saved game.
void Game_Unpause() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#shutdown","title":"Shutdown","text":""},{"location":"zengin/union/sdk/events/#game_exit","title":"Game_Exit","text":"Executes when the player exits the game.
void Game_Exit() {\n\n}\n
"},{"location":"zengin/union/sdk/externals/","title":"Externals","text":""},{"location":"zengin/union/sdk/externals/#externals","title":"Externals","text":"Externals are functions defined by the Gothic engine that can be called from scripts. Union SDK provides symbols for pointers to global zCParser
instances that we can use to interact with the parser and to define a custom external function.
extern zCParser* parser;\nextern zCParser*& parserSoundFX;\nextern zCParser*& parserParticleFX;\nextern zCParser*& parserVisualFX;\nextern zCParser*& parserCamera;\nextern zCParser*& parserMenu;\nextern zCParser*& parserMusic;\n
"},{"location":"zengin/union/sdk/externals/#creating-custom-external","title":"Creating custom external","text":"To create an external we need to define a function handler and register it in the parser. Before we start, it's good to write down a Daedalus function signature so we can see the return and argument types that will be important later.
func string AddNumbers(var int FirstArgument, var int SecondArgument, var string ThirdArgument) {}\n
"},{"location":"zengin/union/sdk/externals/#function-handler","title":"Function handler","text":"External function handler signature must:
return int
or bool
use __cdecl
calling convention (default in C++) take no arguments Inside the handler, we can use the global parser
to pop function arguments and push the return value from/to the stack. It's important to pop the arguments in reverse order and to pop all of them even if we are not going to use them. Similarly, the return value must always be set if any and must never be set if the function returns void
. If we don't follow the rules, the stack may get corrupted and lead to the Gothic crash.
// __cdecl is optional because it's the default calling convention\nint __cdecl AddNumbers_External()\n{\n // Declare arguments\n int FirstArgument;\n int SecondArgument;\n zSTRING ThirdArgument;\n\n // Pop arguments from the stack **IN REVERSE ORDER**\n parser->GetParameter(ThirdArgument);\n parser->GetParameter(SecondArgument);\n parser->GetParameter(FirstArgument);\n\n // Execute function logic\n int result = FirstArgument + SecondArgument;\n zSTRING output = ThirdArgument + zSTRING(result);\n\n // Push return value\n parser->SetReturn(output);\n\n // Return value is ignored, so 0 or 1 is fine.\n return 0;\n}\n
"},{"location":"zengin/union/sdk/externals/#register-external","title":"Register external","text":"Externals should be registered in the parser during the Game_DefineExternals
game event. We need to call parser->DefineExternal
with variadic arguments:
external function name in Daedalus reference to function handler return type ...argument types zPAR_TYPE_VOID
indicates the end of the argument types list void Game_DefineExternals() {\n parser->DefineExternal(\"AddNumbers\", AddNumbers_External, zPAR_TYPE_STRING, zPAR_TYPE_INT, zPAR_TYPE_INT, zPAR_TYPE_STRING, zPAR_TYPE_VOID);\n}\n
Available types are defined by an enum:
enum {\n zPAR_TYPE_VOID,\n zPAR_TYPE_FLOAT,\n zPAR_TYPE_INT,\n zPAR_TYPE_STRING,\n zPAR_TYPE_CLASS,\n zPAR_TYPE_FUNC,\n zPAR_TYPE_PROTOTYPE,\n zPAR_TYPE_INSTANCE\n};\n
"},{"location":"zengin/union/sdk/getting_started/","title":"Getting Started","text":""},{"location":"zengin/union/sdk/getting_started/#getting-started","title":"Getting Started","text":"This article provides a beginner-friendly tutorial for setting up and compiling a Union project. Instructions for installing Union SDK are located at Union SDK.
"},{"location":"zengin/union/sdk/getting_started/#creating-union-plugin","title":"Creating Union plugin","text":""},{"location":"zengin/union/sdk/getting_started/#create-a-visual-studio-project","title":"Create a Visual Studio project","text":"To create a Union plugin project inside Visual Studio we need to use File -> New -> Project. On the next screen, we select \"Union Plugin 1.0m\", and click Next. For the project configuration, we should choose:
Key Value Project name eg. MyPlugin Location Directory where to store the source code Solution Create new solution Solution name eg. MyPlugin We will also check \"Place solution and project in the same directory\" because our plugin consists of only one project, so there is no need to complicate the file structure.
"},{"location":"zengin/union/sdk/getting_started/#file-structure","title":"File Structure","text":"Folder / File Description Engine\u00a0SDK/ In this folder, we have the Gothic Engine API in the form of header files. Most of the files between engines are very similar to each other but they can't be used interchangeably because each engine has slightly different API and addresses of functions. Engine\u00a0SDK/User\u00a0API/ These are empty files that are included in the corresponding engine headers. There are meant for placing additional methods extending classes that can be used for example in Hooks. Plugin/System/ DLL entry point generated by Union. We shouldn't modify anything here. Plugin/Workspace/Interface/ These are header files containing headers and source files important in correct order and an Interface.cpp
file that merges all the code into one file. Plugin/Workspace/Plugin/ Finally, this is the source code of the plugin and especially Plugin.cpp
where we can create code executed on Game Events."},{"location":"zengin/union/sdk/getting_started/#build-configuration","title":"Build Configuration","text":"Each Union plugin may target one or many versions of the Gothic engine and to select the proper API, Union SDK defines several build configurations for every engine, configuration, and also multiplatform build options. Each Target/Configuration combination is named [ENGINE] [CONFIGURATION]
.
Configurations:
Debug: Unoptimized build with debug symbols for development. MD Release: Optimized build for release versions. Runtime Library: Multi-threaded DLL (/MD) MT Release: Optimized build for release versions. Runtime Library: Multi-threaded (/MT) Engines:
G1: Gothic I G1A: Gothic Sequel G2: Gothic II G2A: Gothic II NotR MP x2: Multiplatform target for both Gothic I (G1) and Gothic II NotR (G2A) MP x4: Multiplatform target for all engine versions (Gothic I, Gothic Sequel, Gothic II, Gothic II NotR) For learning Union, it's suggested to select G2A Debug for Gothic II NotR or G1 Debug for Gothic I.
"},{"location":"zengin/union/sdk/getting_started/#project-configuration","title":"Project Configuration","text":"The Union plugin is a regular C++ Visual Studio project so it's possible to configure the project, compiler, linker, and debugger as we wish by going into Project -> Properties. For a starter, we should go to the General tab and check if Platform Toolset is installed and selected. If not, we should select one that's available on our system. Union was created with v100 but it also supports the newest toolkits, so it's best to select a modern one.
In the General tab, we can also specify the Output Directory where the plugin DLL will be placed after the build. During development, we can set it to <GOTHIC_DIR>/System/Autorun
where <GOTHIC_DIR>
is the root folder of the Gothic installation with Union that we will use for testing. Each DLL file placed in System/Autorun
is automatically loaded by Union runtime.
Another method is to put the DLL in the System
directory and modify Gothic.ini
to include
[PLUGIN]\n# Plugin file names without .dll \nPluginList = MyPlugin \n
"},{"location":"zengin/union/sdk/getting_started/#build-the-plugin","title":"Build the plugin","text":"After the initial configuration, we are ready to code something and see if our configuration is working. Let's collect some information about Union and display it with a MessageBox when the game starts. To do so, we locate the Plugin.cpp
file and put our logic in one of the Game Events handlers. The best for that is Game_Init()
because it's executed right after the engine loads every DAT file but before anything else:
void Game_Init() {\n const CPlugin* myPlugin = CPlugin::GetCurrentPlugin();\n\n CStringA gothicVersion;\n switch (Union.GetEngineVersion()) {\n case Engine_G1:\n gothicVersion = \"Gothic I\";\n break;\n case Engine_G1A:\n gothicVersion = \"Gothic Sequel\";\n break;\n case Engine_G2:\n gothicVersion = \"Gothic II\";\n break;\n case Engine_G2A:\n gothicVersion = \"Gothic II NoTR\";\n break;\n default:\n gothicVersion = \"Not possible case. Engine version doesn't match any known engine.\";\n break;\n }\n\n CStringA message = \"Plugin: \" + myPlugin->GetName() + \"\\n\";\n message = message + \"Union Version: \" + Union.GetUnionVersion().ToString() + \"\\n\";\n message = message + \"Gothic Version: \" + gothicVersion;\n\n Message::Info(message, \"Hello World\");\n}\n
Now we can Build (F7) the project to create the DLL. If we have set up Output Directory before, the plugin will deploy directly to the game. Otherwise, we can copy it manually from Bin
to <GOTHIC_DIR>/System/Autorun/MyPlugin.dll
. When we launch the game, a MessageBox should appear right before the main menu:
"},{"location":"zengin/union/sdk/getting_started/#couldnt-build-the-plugin","title":"Couldn't build the plugin?","text":"If you could not build the plugin or it crashed the game, you have to do some debugging and find the root cause of that. For compilation errors look at the Visual Studio Output tab and read the errors.
If they say something about missing toolset, make sure that you selected a Platform Toolset that's installed.
If the proper toolset is selected but doesn't work, make sure that you are configuring the same Configuration that is used for building.
If the plugin was built but the game crashed, you probably selected Configuration for the wrong platform. Gothic 2 Night of the Raven is G2A
and doesn't work with G2
or G1A
. If you are playing Gothic II Classic from Steam, please be advised that it still uses the Night of The Raven engine so the plugin must target G2A
.
"},{"location":"zengin/union/sdk/getting_started/#debugging","title":"Debugging","text":"Union plugins are regular DLLs with executable code hooked to Gothic.exe and running on it, so they can be debugged using the same techniques as any other software.
"},{"location":"zengin/union/sdk/getting_started/#visual-studio-debugger","title":"Visual Studio Debugger","text":"Visual Studio Debugger lets us set breakpoints on any line of code to stop the execution when we reach it. It also gives us a lot of information about the program state at this point. To use the debugger we only need to attach it to the Gothic.exe progress and compile the plugin with Debug configuration.
Option #1: Open Project -> Properties and in the Debugging tab, set Command to the path of our Gothic.exe. Then we can run \"Local Windows Debugger\" in Visual Studio and it starts Gothic with a debugger attached automatically.
Option #2: Open Debug -> Attach to process... and filter process list by \"Gothic\". Run the game separately and when the process appears in Visual Studio, select it and attach to it.
Caveats:
If we attach to the process early, we may get an \"Exception thrown at 0x7B11DB86 (Shw32.dll) in Gothic2.exe: 0xC0000005: Access violation writing location 0x00ABD000.\" right at the beginning. It's fine, just click Continue and Gothic will start properly. If a breakpoint hits when our cursor is locked by Gothic, we may not be able to get the cursor back until execution continues. In this case, we can still use Alt+Tab to switch to Visual Studio and use F5 to continue or F10 to step over. Disabling mouse support in the config may also fix this problem. "},{"location":"zengin/union/sdk/getting_started/#print-debugging","title":"Print Debugging","text":"Printing to some output is probably the simplest form of debugging and Union provides us with several choices.
"},{"location":"zengin/union/sdk/getting_started/#logging-to-zspy","title":"Logging to zSPY","text":"zSPY can be accessed using a global zerr
object. zSPY uses a message filtering system based on the first letter of the message, so our logs should follow the standard format used by other parts of ZenGine. Otherwise, the message may not be visible.
zerr->Message(\"X: MyPlugin: message to zSPY\");\n
"},{"location":"zengin/union/sdk/getting_started/#logging-to-union-console","title":"Logging to Union console","text":"Union console needs to be enabled inside SystemPack.ini
first:
[CORE]\nShowDebugWindow = true\n
Then we can use a global cmd
object behaving like C++ std::cout
to log into the Union console: cmd << \"message to Union console\";\n
"},{"location":"zengin/union/sdk/getting_started/#logging-to-visual-studio","title":"Logging to Visual Studio","text":"Visual Studio can also receive logs from our plugin using:
OutputDebugString(\"message to Visual Studio\");\n
This method works only when we have a debugger attached, so it's not recommended for general logging."},{"location":"zengin/union/sdk/hooks/","title":"Hooks","text":""},{"location":"zengin/union/sdk/hooks/#hooks","title":"Hooks","text":"Union provides a hooks system that lets us intercept calls to the engine functions and methods with our custom interceptor. To hook a function or method we need to know its address which can be acquired either from Engine SDK/[Engine]/Names_[Engine].hpp
or from the engine classes headers Engine SDK/[Engine]/Headers
.
"},{"location":"zengin/union/sdk/hooks/#intercepting-functions","title":"Intercepting functions","text":"To declare a hook we can use CInvoke
class or HOOK AS
macros.
CInvoke<function_type> Ivk_HookName(orignal_function_address, our_interceptor_function, hook_flags);\n\nHOOK Ivk_HookName AS(orignal_function_address, our_interceptor_function, hook_flags);\n
"},{"location":"zengin/union/sdk/hooks/#regular-functions","title":"Regular functions","text":"Regular functions are the functions declared outside of classes.
// 0x0042C450 int __cdecl Apply_Options_Video(void)\n\n// Forward declaration\nint Apply_Options_Video(); \n\n// Hook declaration\nCInvoke<int(*)()> Ivk_Apply_Options_Video(0x0042C450, &Apply_Options_Video);\n// Equivalent:\n// HOOK Ivk_Apply_Options_Video AS(0x0042C450, &Apply_Options_Video);\n\n// Implementation of interceptor\nint Apply_Options_Video() {\n Message::Info(\"Before original Apply_Options_Video()\");\n\n // Original function can be called using CInvoke pointer.\n int result = Ivk_Apply_Options_Video();\n\n Message::Info(\"After original Apply_Options_Video()\");\n\n return result;\n}\n
"},{"location":"zengin/union/sdk/hooks/#member-function","title":"Member function","text":"Member functions are the functions declared as non-static class members and they take a class instance pointer as an implicit first argument (__thiscall
calling convention). We can hook them in two ways using either a regular function or declaring a new method in User API.
"},{"location":"zengin/union/sdk/hooks/#option-1---regular-function","title":"Option #1 - Regular function","text":"// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &)\n\n// Forward declaration\nint __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context);\n\n// Hook declaration\nCInvoke<int(__fastcall *)(zCVob* _this, zTRenderContext& context)> Ivk_zCVob_Render(0x006015D0, &zCVob_Render);\n// Equivalent:\n// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob_Render);\n\n// Implementation of interceptor as regular function\n// Notice the first argument that's a pointer to class instance (this)\nint __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context) {\n if(_this == player) {\n screen->PrintCX(1000, \"Rendering a player zCVob\");\n }\n\n // Call original method\n return Ivk_zCVob_Render(_this, context);\n}\n
"},{"location":"zengin/union/sdk/hooks/#option-2---user-api","title":"Option #2 - User API","text":"In Engine SDK/User API
we can find a .inc
file for the class we are hooking and define a new member method there. In this case, we are looking for zCVob.inc
:
// Supported with union (c) 2020 Union team\n\n// User API for zCVob\n// Add your methods here\n\nint RenderUnion(zTRenderContext& context);\n
Then we can declare the hook pointing to our member method:
// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &)\n\n// Hook declaration\nCInvoke<int(__fastcall zCVob::*)(zTRenderContext& context)> Ivk_zCVob_Render(0x006015D0, &zCVob::RenderUnion);\n// Equivalent:\n// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob::RenderUnion);\n\n// Implementation of interceptor method\nint zCVob::RenderUnion(zTRenderContext& context) {\n if(this == player) {\n screen->PrintCX(1000, \"Rendering a player zCVob\");\n }\n\n // Call original method\n return Ivk_zCVob_Render(this, context);\n}\n
"},{"location":"zengin/union/sdk/hooks/#hook-flags","title":"Hook flags","text":"In the third argument of CInvoke
we can provide hook flags. The default value is IVK_AUTO
.
enum EInterMode\n{\n // Hook will not intercept the function.\n IVK_DISABLED = 1 << 1,\n\n // Normal hook. If other hook is already defined for the same address, an error pops up.\n IVK_NORMAL = 1 << 2,\n\n // Hook will automatically create an interception tree to allow multiple hooks for the same address.\n IVK_AUTO = 1 << 3,\n\n // Overrides any hook defined for the same address before.\n IVK_REDEFINE = 1 << 4,\n\n // Makes it impossible to override or disable the hook.\n // It should be used only in very specific cases.\n IVK_PROTECTED = 1 << 5,\n\n // Same as IVK_DISABLED\n IVK_READONLY = IVK_DISABLED\n};\n
"},{"location":"zengin/union/sdk/hooks/#credits","title":"Credits","text":"Examples are taken from the Union lessons in Russian created by Gratt on worldofplayers.ru/threads/41490/
"},{"location":"zengin/worlds/","title":"Worlds","text":""},{"location":"zengin/worlds/#worlds","title":"Worlds","text":"Acknowledgment
This article is heavily inspired by various tutorials from the polish TheModders forums.
Worlds, saved as .ZEN
files in ZenGin, are archives that contain the world mesh (model), BSP tree, materials and the information of all objects in the world. These objects are called VOBs (\"virtual objects\"). ZEN files can be saved in two ways; compiled and uncompiled. The compiled version is a full-fledged level with a terrain model. Uncompiled ZENs only save the VOB tree and are meant for specific use-cases.
Spacer is used to create these .ZEN
files. There are also other world editors. The way of doing things can vary between these editors, so the specifics will be discussed in separate articles for those tools; at the same time, a lot of knowledge carries over between them. Also have in mind that Spacer is the least comfortable of the editors.
"},{"location":"zengin/worlds/#world-contents","title":"World contents","text":"The content of worlds in Gothic can be roughly separated in the following way:
Base level mesh - terrain and buildings, sometimes also trees. VOBs (zCVob
and subclasses) - all interactive objects, items, foliage, small rocks, huts, furniture, ramps etc. Asides from those elements, there are also many invisible VOBs, such as:
Waypoints (zCVobWaypoint
) - used for NPC navigation. Freepoints (zCVobSpot
) - used mainly for NPC routines and roaming behavior for monsters. Startpoints (zCVobStartpoint
) - used only to spawn the player when starting a new game. Teleporting between levels is handled with scripts and uses freepoints to determine where the player will appear. Sound emitters Music zones oCZoneMusic
- music which plays inside the bounding box of this zone. oCZoneMusicDefault
- default music which plays whenever the player is not inside some oCZoneMusic
. Fog zones (zCZoneZFog
) - areas which add fog, e.g. like in swamp areas where the sky is not visible. The setting to fade out the sky is optional though. PFX - particle effects (fire, smoke, fireflies, falling leaves etc.) Note
This list isn't exhaustive.
World also contains information about all materials used by level mesh and VOBs. They are stored in the form of zCMaterial
instances.
"},{"location":"zengin/worlds/#creating-a-zen-file","title":"Creating a ZEN file","text":"Before VOBs can be added to a world model, the world needs to be compiled. After importing a 3ds model, the world can be compiled as an outdoor or indoor world and saved as a ZEN.
The submeshes used in ZEN files have triangle count limits (it is also advisable to keep triangle count for each submesh under 50k for performance reasons). To get around this limitation and to parallelize work on various areas, it is possible to join multiple ZEN files together, which is done with special macros.
If you take a look at the original maps for Gothic 2, you can notice that they are in folders, where there's e.g. a file called NEWWORLD.ZEN
and multiple .ZEN
files with \"part\" in their name. The latter are the sub-zens used to create the full level.
However, a possibly more comfortable workflow is to have a single world mesh which is internally separated into multiple submeshes. This way triangle count limits won't be exceeded and the world won't need compiling from parts. As a trade-off, it is likely that it won't be possible for multiple people to work on the ZEN world at the same time.
"},{"location":"zengin/worlds/#lighting","title":"Lighting","text":"There are two light types in the game:
Static lights, which are baked onto the level. They can cast shadows (these only take static VOBs into consideration) and don't leak through walls. These have to be recompiled after making changes, but this process should only take moments. Static lights have the downside of only working in indoor worlds and in rooms which are closed with portals. Dynamic lights are calculated during runtime, which allows them to move and change properties (their color, for example), but has a performance cost. Additionally, they don't look the best and will often leak through walls. It is generally advised to use static lights whenever possible.
"},{"location":"zengin/worlds/#portals","title":"Portals","text":"Portals are special parts of outdoor world meshes which separate interiors from exteriors. This allows the level to have dark areas: otherwise interiors are lit the same way as any outside area. Additionally, portals help with performance (interiors aren't rendered unless the player is nearby). Creation of portals has many caveats and will be discussed in a separate article. Portals are also related to NPC behavior (e.g. setting ownership of a room).
"},{"location":"zengin/worlds/#water","title":"Water","text":"Water is a special surface in the world. It has to be properly modelled, and its material has to be set up correctly. You can read more about it in the dedicated article.
"},{"location":"zengin/worlds/#optimisation","title":"Optimisation","text":"The game uses occlusion culling, which means that if an object is covered by another object, it is not rendered and saves performance. This means that the performance in a level can be boosted by a lot by creating city walls and mountains and valleys which separate areas.
Occlusion culling isn't a perfect process, so there's also the option of adding GHOSTOCCLUDERs, which are invisible walls which stop areas behind them from rendering. They are a part of the world mesh and are created by assigning a material called GHOSTOCCLUDER to chosen faces. The color of the material is traditionally purplish-blue or pink, but the material itself is not rendered in-game, so this is only to make them stand apart from the rest of the level during modelling. To get more technical, these occluder walls are used to help the BSP algorithm which runs during world compilation.
As mentioned before, another ways of optimisation are portals and limiting the number of dynamic lights. It is also not advisable to make many VOBs be affected by wind.
"},{"location":"zengin/worlds/spacer/","title":"Spacer","text":""},{"location":"zengin/worlds/spacer/#spacer","title":"Spacer","text":"Spacer is the original world editor used to create maps in Gothic and it's installed by the MDK installer.
A good .ZEN
file to start experimenting with Spacer is Toten Insel. It's a simple level which should load without issues for everyone. The map contains a custom texture, but it can be safely ignored.
"},{"location":"zengin/worlds/spacer/#introduction","title":"Introduction","text":"Upon launching Spacer, multiple windows will appear. They are:
The main viewport (black with text on launch) The vobtree - allows to browse and select the objects already placed in a level The object window - it has 3 tabs: Create, Modify and \"...\". Toolbars - there's two of them and each button has a hover hint. The help window - sometimes when clicking on something, this window will show a description. It's usually empty though. The objectpages window - allows access to specific VOB settings. The contents of this window be changed with buttons on the horizontal toolbar. Other windows dedicated to specific functionalities can also be opened or toggled (Window tab in the viewport or the horizontal toolbar).
When importing a mesh instead of a .ZEN
file, some things will change. In this mode, objectpages has material data, one of the toolbars changes completely and the vobtree window changes into a texture browser.
"},{"location":"zengin/worlds/spacer/#configuration","title":"Configuration","text":"Before doing anything else, you will probably want to change a few settings first. Select Settings: View
in the Settings tab in the main viewport to increase the viewport resolution. After doing that, press Align Toolwindows at Screen
or Align Toolwindows at Spacer
in the Window tab to clean up the window placement. You might still need to move some of the tool windows around after this, as they can overlap.
The most comfortable option we found was to set the resolution to something slightly smaller than the screen resolution (e.g. 1600:900 on a 1920:1080 screen) and then aligning the tool windows to screen.
To help with the control sensitivity issues, change the camera movement speed in the Settings: General
.
"},{"location":"zengin/worlds/spacer/#viewport-controls","title":"Viewport controls","text":"The camera has multiple modes of operation. Some of the controls may sound confusing, but will make sense once you try them.
Default selection mode
Arrows move the camera back and forward and rotate it sideways. A
moves the camera up and Y
lowers it.
PageUp
and PageDown
rotate the camera up and down. End
resets this rotation.
Selecting VOBs is done by simply pointing at them with the mouse and clicking.
First-person selection mode
Toggled by the F3
button.
In this mode, you can point the camera with your mouse, and selection is done by pointing the green reticle at a VOB and clicking LMB
. Arrows now move the camera parallel to itself (including sideways).
PageUp
and PageDown
still rotate the camera up and down, but it's better not to use them because it affects how the arrow movement behaves. End
resets this rotation.
Default VOB movement mode
When a VOB is selected, press M
to enter and exit this mode.
The arrows now move the VOB horizontally. Moving it up and down is done with A
and Y
.
The keys above the arrows now rotate the VOB:
Axis 1: Delete
and PageDown
Axis 2: Insert
and PageUp
Axis 3: Home
and End
First-person VOB movement mode
When a VOB is selected, press T
to enter and exit this mode.
The controls are the same as the default selection mode, but the camera is now placed at the selected VOB and it moves with the camera.
One caveat is that the controls are in the local space of the object. What this basically means is that if you rotated the object in any other way than horizontally, the movement and rotation will now be skewed.
Mixed VOB movement mode
When a VOB is selected, press C
to enter and exit this mode. The VOB is now controlled like in the first-person movement mode, but the camera is not placed at the VOB: in other words, the camera remains in the same place.
General
Holding down Shift
speeds up the camera in all of the modes. The numpad can be used for rotating instead of the buttons above the arrows. Both movement modes can be used from either of the selection modes. Movement modes can be selected from the vertical toolbar. This toolbar also has a \"toggle camera position\" button; this switches between two camera placements, which can be controlled independently.
The objects location can also be entered manually through the object window: open the Internals folder and select trafoOSToWSPos
to input them at the bottom of the window. Don't forget to press \"Apply\". Unfortunately the rotation setting uses an odd format and can't be set manually.
"},{"location":"zengin/worlds/spacer/#basic-usage","title":"Basic usage","text":"This section covers some of the basic things done in the editor.
"},{"location":"zengin/worlds/spacer/#inserting-a-vob","title":"Inserting a VOB","text":" In the Create tab in the Objects window, select the VOB type. Choose zcVob
to add a simple decorative model. Right click anywhere on the viewport Select the insert option (Insert [zcVob]
in this case) A VOB without a mesh will be created in the middle of the screen. Try to not deselect it, but if you do, it can be found in the vobtree under the appropriate folder (zcVob
in this case); it can be identified by a green dot. In the Modify tab in the Object window, select \"visual\". Insert the model name in the text form at the bottom of the window. You can use pc_lob_sleeper3.3ds
for now; this mesh should be present in both Gothic 1 and 2. If you unpacked the meshes while installing the MDK or with GothicVDFS, you can also browse to the file using the file button next to the text form. Make sure to click the Apply button. Do this after making any changes in the Object window or they will be lost. Tip
You can use the VOB Bilder tool to comfortably browse model images and names. An online version is currently available here. The UI on the website is in Polish but it's simple enough to not matter.
To make the VOB have collision in-game, double click on cdDyn
(\"collision detection dynamic\") to set it to true. Sometimes this is unadvised, e.g. with bushes or grass. Tip
When placing pickable items, you can press the \"apply physics on selected VOB\" button in the vertical toolbar to make the item drop on the ground. It can save you a lot of work with placing those items. This won't work with a plain cVob though.
"},{"location":"zengin/worlds/spacer/#common-vob-settings","title":"Common VOB settings","text":"VOB settings vary depending on what the VOB type is. They all have common parameters of the base VOB class though. The full description of a zCVob class can be found here.
"},{"location":"zengin/worlds/spacer/#issues","title":"Issues","text":"Spacer 2 received the last update in 2003 and is a very buggy tool. Here are some known issues.
Framerate dependence
The speed of camera in Spacer depends on the framerate. Depending on the angle of the camera and the level, Spacer can have huge framerate, which will make the camera move too quick.
You can try to limit the framerate of Spacer with external tools, but your mileage may vary. Such tools often only limit rendering using fake Vsync, but the underlying logic of the program can still run too fast.
Using the grid snap function can help when the framerate is high, but again: your mileage may vary.
Random freezes and crashes
Spacer will freeze or crash quite often at seemingly random moments. It is extremely important to save often and back up your work.
One of the common ways the editor can freeze is when rotating the camera vertically when the framerate is very high. In that case, changing the camera mode to F3 and back can sometimes help.
Copying VOBs
When copy-pasting a VOB in Spacer (right click menu), the new VOB might be created as a child of the original one and moving one of them will move both. This doesn't seem to be consistent, but it's worth checking before you accidentally ruin the careful placement of the original VOB.
"},{"location":"zengin/worlds/spacer/#troubleshooting","title":"Troubleshooting","text":"You can have issues with loading a ZEN or a world model for a multitude of reasons. Here is some of the known ones.
Some terrain models aren't set up or exported properly. Maps which use custom assets will cause issues or won't even load unless these assets are included in appropriate directories. The severity of this is different depending on the asset type. For example, textures will be replaced with a placeholder, but animations will cause crashes. Note
This section is not exhaustive.
"},{"location":"zengin/worlds/spacer/#creating-zens","title":"Creating ZENs","text":"Presented here are the ways of working with new terrain models.
"},{"location":"zengin/worlds/spacer/#compiling-a-world-mesh","title":"Compiling a world mesh","text":"To create a completely new ZEN, you will first need a level mesh. These can be made from scratch or downloaded, but be aware that meshes, which aren't properly prepared won't compile correctly (you won't be able to move in the viewport). As with any other mesh in Gothic, it has to be in the 3ds format. It is recommended to place the mesh file somewhere in the _work/Data/Meshes
(can be your own subfolder).
You can find free terrain models here if you want to practice this. Note that not all of them might compile properly; this one should be fine though.
First, load the mesh from the File tab of the viewport. To compile the mesh, press Compile World
in the World tab. From here, multiple options are available:
Indoor/Outdoor: determines if the world will have a sky and the way that lighting behaves. Detect leaks: might be related to checking if indoor (\"underground\") worlds have holes in them. In some games such holes can cause performance issues, perhaps it's the same here. Doesn't hurt to enable it. Quick compile: self-explanatory, but the exact effects of this are unknown. Polycheck: presumably checks if the model doesn't exceed triangle limits. Editormode:
On: Spacer will load the mesh in editor mode, which allows you to change materials assigned to triangles and other mesh operations. It is more comfortable to do these things in an external 3D editor, but sometimes using this is recommended, e.g. for setting up portals. You can save the model as a .3ds
in this mode.
Off: Spacer will create a ZEN where you can normally place VOBs. You can now save the world as a compiled ZEN and add VOBs to it.
"},{"location":"zengin/worlds/spacer/#compiling-a-world-from-multiple-meshes","title":"Compiling a world from multiple meshes","text":"First and foremost, the models used for this must be properly positioned and separated in your 3D editor of choice. Then each section must be exported as separate .3ds
files. After that, compile each model and save it as a compiled ZEN. Place them in their own folder. You can place VOBs in those ZEN files, the VOB trees will be merged too.
Now, to join these zens together, you will need to define a macro in Tools>Macros
. These are pretty much identical except for the ZEN list; for example, the Mining Colony ZEN in Gothic 2 (OLDWORLD.ZEN
) is comprised of two models, and the macro looks like this:
reset\nset error 3\nLoad world oldworld\\SURFACE.ZEN\nLoad world oldworld\\OLDCAMP.ZEN\ncompile world outdoor\ncompile light high\n
Then you double-click the macro name to run it and wait. The macro contains the reset directive, but it's worth doing it on a freshly opened Spacer instance just to be safe.
Keep in mind that compiling a world from multiple ZENs is meant as a final step in level production. This is because doing it will cause issues with culling and stop interiors from rendering (and thus stop you from editing it). Instead, the part ZENs are filled with VOBs separately and the world is compiled as a final step before testing the map.
"},{"location":"zengin/worlds/spacer/#updating-world-meshes-in-a-compiled-zen","title":"Updating world meshes in a compiled ZEN","text":"Ideally, updating the world mesh would be avoided, but it's an inevitable need when iterating a map design. Doing this in the original Spacer might not be impossible, but it is generally avoided and Spacer.NET or other editors are used for this instead.
"},{"location":"zengin/worlds/Classes/zCMaterial/","title":"zCMaterial","text":""},{"location":"zengin/worlds/Classes/zCMaterial/#zcmaterial","title":"zCMaterial","text":"Quick Infos
Class Name: zCMaterial
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
zCMaterial
class describes the properties of the game materials.
Danger
zCMaterial
objects are only saved in binary .ZEN
files.
"},{"location":"zengin/worlds/Classes/zCMaterial/#class-members","title":"Class members","text":"Gothic 1Gothic 2 zCMaterial Internals name = \"\" matGroup = UNDEF color = 255 255 255 255 smoothAngle = 60 texture = \"\" texScale = 512 512 texAniFPS = 0 texAniMapMode = NONE texAniMapDir = 0 0 noCollDet = FALSE noLightmap = FALSE lodDontCollapse = FALSE detailObject = \"\" zCMaterial Internals defaultMapping = 2.34375 2.34375 name = \"\" matGroup = UNDEF color = 255 255 255 255 smoothAngle = 60 texture = \"\" texScale = 512 512 texAniFPS = 0 texAniMapMode = NONE texAniMapDir = 0 0 noCollDet = FALSE noLightmap = FALSE lodDontCollapse = FALSE detailObject = \"\" detailObjectScale = 1 forceOccluder = FALSE environmentalMapping = FALSE environmentalMappingStrength = 1 waveMode = NONE waveSpeed = FALSE waveMaxAmplitude = 30 waveGridSize = 100 ignoreSunLight = FALSE alphaFunc = NONE "},{"location":"zengin/worlds/Classes/zCMaterial/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCMaterial/#defaultmapping","title":"defaultMapping
","text":"Default material mapping.
"},{"location":"zengin/worlds/Classes/zCMaterial/#name","title":"name
","text":"Material name. In most cases corresponds to the name of the texture map.
"},{"location":"zengin/worlds/Classes/zCMaterial/#matgroup","title":"matGroup
","text":"Sound accompaniment of the material. Must be specified to produce the correct sounds when moving across the specified material.
Accepted values:
UNDEF
- Undefined. METAL
- Metal. STONE
- Stone. WOOD
- Wood. EARTH
- Earth. WATER
- Water. SNOW
- Snow. "},{"location":"zengin/worlds/Classes/zCMaterial/#color","title":"color
","text":"Texture replacement color in RGBA format. Polygon is in this color until engine applies the texture.
"},{"location":"zengin/worlds/Classes/zCMaterial/#smoothangle","title":"smoothAngle
","text":"Defines the angle of material smoothing between two faces.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texture","title":"texture
","text":"Defines the name of the texture file used for the material, which also determines whether the texture is animated or static.
To create animated textures, add a suffix to the file name _A0
, e.g., NW_Fire_A0.TGA
, NW_Fire_A1.TGA
etc. The texture NW_Fire_A0.TGA
is the first frame. The game engine will automatically search your hard drive for remaining animation files.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texscale","title":"texScale
","text":"Defines the scaling along the X and Y axes. Assigns the necessary texture coordinates to polygons.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texanifps","title":"texAniFPS
","text":"Defines the FPS (frames per seconds) of texture animation, but only if the texture is animated (NAME_A0.*
).
"},{"location":"zengin/worlds/Classes/zCMaterial/#texanimapmode","title":"texAniMapMode
","text":"Texture animation mode.
Accepted values:
NONE
- No texture animation. LINEAR
- Linear texture animation. "},{"location":"zengin/worlds/Classes/zCMaterial/#texanimapdir","title":"texAniMapDir
","text":"Defines the direction and movement speed of animated textures. The values should be significantly lower than 1 (For example 0.00005).
Danger
The animation movement is only enabled when texAniMapMode
is set to LINEAR
mode.
"},{"location":"zengin/worlds/Classes/zCMaterial/#nocolldet","title":"noCollDet
","text":"Defines if collision detection is disabled.
Accepted values:
TRUE
- Collisions disabled. FALSE
- Collisions enabled. "},{"location":"zengin/worlds/Classes/zCMaterial/#nolightmap","title":"noLightmap
","text":"Defines if light map is disabled.
Accepted values:
TRUE
- Disable baking of light maps on the material. FALSE
- Enable baking of light maps on the material. "},{"location":"zengin/worlds/Classes/zCMaterial/#loddontcollapse","title":"lodDontCollapse
","text":"If you activate this option, the texture will not degrade when the camera moves away.
Accepted values:
TRUE
- Disable texture degradation. FALSE
- Enable texture degradation. Note
To prevent the texture from being distorted, you can cancel the creation of a MipMap. It is advisable to use for small objects.
"},{"location":"zengin/worlds/Classes/zCMaterial/#detailobject","title":"detailObject
","text":"An option that allows you to complement the material with an additional texture.
"},{"location":"zengin/worlds/Classes/zCMaterial/#detailobjectscale","title":"detailObjectScale
","text":"Tiling of the overlay image selected in the detailObject
property.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#forceoccluder","title":"forceOccluder
","text":"No information provided.
Accepted values:
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#environmentalmapping","title":"environmentalMapping
","text":"Environment mapping mode. Creates glare on the texture.
Accepted values:
TRUE
- Enable reflection mode. FALSE
- Disable reflection mode. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#environmentalmappingstrength","title":"environmentalMappingStrength
","text":"The strength of environmental reflection on a model.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavemode","title":"waveMode
","text":"Enable wave simulation mode. For example, AMBIENT_GROUND
is used for water textures.
Accepted values:
NONE
- Wave simulation is disabled. AMBIENT_GROUND
- Wave simulation is enabled. GROUND
- No information. AMBIENT_WALL
- No information. WALL
- No information. ENV
- No information. AMBIENT_WIND
- No information. WIND
- No information. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavespeed","title":"waveSpeed
","text":"Wave speed.
Accepted values:
SLOW
- Slow. NORMAL
- Normal. FAST
- Fast. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavemaxamplitude","title":"waveMaxAmplitude
","text":"Maximum wave amplitude.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavegridsize","title":"waveGridSize
","text":"Wave mesh size.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#ignoresunlight","title":"ignoreSunLight
","text":"Defines if the material ignores sunlight (doesn't cast shadows).
Accepted values:
TRUE
- Ignore. FALSE
- Don't ignore. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#alphafunc","title":"alphaFunc
","text":"Alpha channel blending function.
Accepted values:
NONE
- None. MAT_DEFAULT
- Use texture alpha channel. BLEND
- Mixing. SUB
- Subtraction. MUL
- Multiplication. MUL2
- Multiplication 2. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/","title":"zCVob","text":""},{"location":"zengin/worlds/Classes/zCVob/#zcvob","title":"zCVob","text":"Quick Infos
Class Name: zCVob
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents so-called virtual objects which appear in the game world. zCVob
is the base class for all virtual objects which include everything from static models like boxes to interactive elements like doors and chests and invisible trigger objects.
"},{"location":"zengin/worlds/Classes/zCVob/#class-members","title":"Class members","text":"Properties of a zCVob class are split into two parts. The Internals are hardly ever needed to be edited manually, they are changed by e.g. moving an object in Spacer. On the other hand the Vob properties can only be changed by the Objects context menu in Spacer.
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE visual = NULL ai = NULL zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE visualAniMode = NONE visualAniModeStrength = 0.0 vobFarClipZScale = 1.0 cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE zbias = 1 isAmbient = FALSE visual = NULL ai = NULL zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE visual = NULL ai = NULL sleepMode = 0 nextOnTimer = 0.0 zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE visualAniMode = NONE visualAniModeStrength = 0.0 vobFarClipZScale = 1.0 cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE zbias = 1 isAmbient = FALSE visual = NULL ai = NULL sleepMode = 0 nextOnTimer = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/#pack","title":"pack
","text":"Internal property which indicates how the data associated with this virtual object is stored.
"},{"location":"zengin/worlds/Classes/zCVob/#presetname","title":"presetName
","text":"The name of the template that was used to create this virtual object.
"},{"location":"zengin/worlds/Classes/zCVob/#bbox3dws","title":"bbox3DWS
","text":"The 3-dimensional bounding box of this virtual object. Defined by two opposite diagonal points (1x, 1y, 1z
, 2x, 2y, 2z
). This is used in conjunction with cdStatic and cdDyn calculate collisions and interactions with other game objects (NPCs, items, etc.).
Interaction processing begins when object volumes intersect. For example, when the player enters the world change trigger area, the engine loads another game level based on the parameters this trigger. All this happens when the main character's BoundingBox intersects with the trigger's BoundingBox.
The BoundingBox can only be changed using the Edit the Bbox
button in Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/#trafoostowsrot","title":"trafoOSToWSRot
","text":"The rotation of this virtual object in world space, represented by a 3x3 rotation matrix.
"},{"location":"zengin/worlds/Classes/zCVob/#trafoostowspos","title":"trafoOSToWSPos
","text":"Coordinates of the object in world space relative to the center.
Note
This refers to the center of coordinates of the .3DS
file of the game world on which the ZEN
file is built.
The coordinates are set automatically the first time an instance of the class is inserted into the game world. You can change them either directly by entering numerical values in the corresponding fields of the parameter, by moving the vob in spacer.
"},{"location":"zengin/worlds/Classes/zCVob/#vobname","title":"vobName
","text":"An identifier of a zCVob shown in the editor and sometimes used in scripts. The name can be left blank.
For some object classes, entering a name is required: zCVobSpot, zCVobWaypoint, zCTrigger etc.
Danger
Setting a name for every static and insignificant object can lead to an error when parsing the game world.
"},{"location":"zengin/worlds/Classes/zCVob/#visual","title":"visual
","text":"The name of the visual component associated with this object, usually a name of a file.
Following formats are supported:
*.3DS
- Static objects *.PFX
- Particle effects *.TGA
- Textures *.MDS
, *.ASC
- Interactive objects *.MMS
- Animated objects "},{"location":"zengin/worlds/Classes/zCVob/#showvisual","title":"showVisual
","text":"Indicates whether this object should display its visual.
Accepted values:
TRUE
- Display. FALSE
- Do not display. "},{"location":"zengin/worlds/Classes/zCVob/#visualcamalign","title":"visualCamAlign
","text":"Option to align objects relative to the camera.
Accepted values:
NONE
- Not used. YAW
- The object always faces the player. FULL
- The object is aligned relative to the world axes. Note
This may be used with grass or flowers which only consist of a 2-dimensional sprite to have it always face the camera.
"},{"location":"zengin/worlds/Classes/zCVob/#visualanimode","title":"visualAniMode
","text":"Wind simulation option. Used in conjunction with the visualAniModeStrength parameter.
Accepted values:
NONE
- Not used. WIND
- Strong wind effect. Acceptable for herbs. WIND2
- Light wind effect. Acceptable for trees. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#visualanimodestrength","title":"visualAniModeStrength
","text":"Wind power animation multiplier. Small values such as 0.001
are typically used. Used in conjunction with the visualAniMode parameter.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#vobfarclipzscale","title":"vobFarClipZScale
","text":"Sets the loading range of the VOB object. Depends on the VOB drawing distance specified using the zCZoneVobFarPlane
object.
The range of values is from 0.0
to 2.0
.
With a value of 0.0
, the object is not visible, but collisions are calculated. With a value of 2.0
, the zCVob
drawing range is the same as the draw distance specified in zCZoneVobFarPlane
object.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#cdstatic","title":"cdStatic
","text":"Determines if the virtual object will collide with the static objects (world mesh and other VOBs with cdStatic on).
Accepted values:
TRUE
- Collide with static objects. FALSE
- Don't collide static objects. Tip
A situation often arises when objects \u201crefuse\u201d to move beyond a certain point on the surface. This happens when cdStatic is set to TRUE
, i.e. the object cannot cross the surface another static object. In this case, it is enough to disable the cdStatic parameter for the duration of the move, and turn it on again after the move.
"},{"location":"zengin/worlds/Classes/zCVob/#cddyn","title":"cdDyn
","text":"Determines if the virtual object will collide with dynamic objects (NPCs, items, etc.). This basically determines if the object has collision during gameplay.
Accepted values:
TRUE
- Collide with dynamic objects. FALSE
- Don't collide with dynamic objects. "},{"location":"zengin/worlds/Classes/zCVob/#staticvob","title":"staticVob
","text":"Determines if the VOB is taken into consideration in static lighting calculations in Indoor spaces. Usually enabled in decorative Vobs, but some of the interactive ones have it disabled.
Accepted values:
TRUE
- Calculate the shadow of the object. FALSE
- Do not calculate the shadow of the object. Note
The shadow is calculated when compiling light in Low, Middle or High mode.
"},{"location":"zengin/worlds/Classes/zCVob/#dynshadow","title":"dynShadow
","text":"Indicates whether the object will cast a shadow when affected by dynamic light (e.g. torches).
Accepted values:
DS_NONE
- No shadow. DS_BLOB
- Casts a circular shadow. "},{"location":"zengin/worlds/Classes/zCVob/#zbias","title":"zbias
","text":"The depth-bias for this virtual object.
Can be used remove texture flickering if a .TGA
file is used as rendering.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#isambient","title":"isAmbient
","text":"Indicates that this virtual object is ambient. It looks like this setting was a system used during development when access to the game's source code was available. Basically, the global variable zCWorld::s_bAmbientVobsEnabled
could be used to hide or show virtual objects which have the isAmbient
flag set. In release builds, this variable is always set to true, thus the isAmbient
flag does not have any perceivable effect on the game. It follows, that this field should be ignored by most implementations.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#sleepmode","title":"sleepMode
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/#nextontimer","title":"nextOnTimer
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/","title":"zCCSCamera","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#zccscamera","title":"zCCSCamera","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCCSCamera
Version Identifiers: \u2014 Gothic I: 30720
\u2014 Gothic II: 33793
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL paused = FALSE started = FALSE gotoTimeMode = FALSE csTime = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#camtrjfor","title":"camTrjFOR
","text":"The coordinate system of the key frames of the camera trajectory.
Accepted values:
WORLD
\u2014 Positions are relative to the global world coordinate system. OBJECT
\u2014 Positions are relative to the position of the camera object in the previous frame. Essentially, when the camera travels along the keyframes each subsequent keyframe's position is relative to the position of the previous keyframe. The position of the first keyframe is relative to the initial position of the camera. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#targettrjfor","title":"targetTrjFOR
","text":"The keyframe coordinate system of the target camera trajectory.
Accepted values:
WORLD
\u2014 Positions are relative to the global world coordinate system. OBJECT
\u2014 Positions are relative to the position of the camera object in the previous frame. Essentially, when the camera travels along the keyframes each subsequent keyframe's position is relative to the position of the previous keyframe. The position of the first keyframe is relative to the initial position of the camera. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#loopmode","title":"loopMode
","text":"The repetition mode of the camera animation.
Accepted values:
NONE
\u2014 The camera animation stops after the last frame is reached. RESTART
\u2014 The camera animation starts from the beginning after the last frame is reached. The ModKit states, that this is only useful if the animation is to be interrupted by scripts or triggers. PINGPONG
\u2014 The camera animation re-plays the keyframes in reverse order after reaching the last frame. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#spllerpmode","title":"splLerpMode
","text":"Adjust camera orientation while moving.
Accepted values:
UNDEF
\u2014 Unset. PATH
\u2014 The camera's orientation is specified by the slope of the target path spline. PATH_IGNOREROLL
\u2014 The camera's orientation is similar to PATH
with the only difference being that the camera's XZ plane is always parallel to the world's XZ plane. PATH_ROT_SAMPLES
\u2014 The camera's orientation is based on the keyframes. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#ignoreforvobrotcam","title":"ignoreFORVobRotCam
","text":"Determines whether the orientation to reference VOB objects should be taken into account when passing through key frames.
Accepted values:
TRUE
\u2014 Orientation to VOB reference objects is ignored. This can be useful if VOB objects appear that are calculated by the rotation animation. After this, the orientation is taken into account only once at the beginning of the movement. FALSE
\u2014 Orientation is not ignored. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#ignoreforvobrottarget","title":"ignoreFORVobRotTarget
","text":"Determines the need to take into account the orientation of target key frames to reference VOB objects.
Accepted values:
TRUE
\u2014 Orientation to VOB reference objects is ignored. Orientation to VOB reference objects is ignored. May be necessary when rotation of reference VOBs defines animation. After this, the orientation is taken into account only once at the beginning of the movement. FALSE
\u2014 Orientation is not ignored. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#adapttosurroundings","title":"adaptToSurroundings
","text":"Indicates the need for dynamic adaptation to the environment.
Accepted values:
TRUE
\u2014 Enable adaptation. FALSE
\u2014 Disable adaptation. The camera will not adapt to its environment. Useful in cases where the keyframes in the world have taken an absolute position (i.e. the camTrjFOR parameter is set to WORLD
). "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#easetofirstkey","title":"easeToFirstKey
","text":"Gives a smooth transition of camera position from the first keyframe to the last, if possible.
Accepted values:
TRUE
\u2014 Smooth transition if possible. FALSE
\u2014 No smooth transition. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#easefromlastkey","title":"easeFromLastKey
","text":"Gives a smooth transition of camera position from the last keyframe to the first, if possible.
Accepted values:
TRUE
\u2014 Smooth transition if possible. FALSE
\u2014 No smooth transition. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#totaltime","title":"totalTime
","text":"The duration of the camera animation in seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamfocusvobname","title":"autoCamFocusVobName
","text":"The name of the VOB object which the camera will automatically focus.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamplayermovable","title":"autoCamPlayerMovable
","text":"Indicates whether the player will be able to move when moving the camera animation.
Accepted values:
TRUE
\u2014 The player will be able to move. FALSE
\u2014 The player is motionless. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamuntriggeronlastkey","title":"autoCamUntriggerOnLastKey
","text":"Emit an OnUntrigger
event after reaching the last animation frame.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamuntriggeronlastkeydelay","title":"autoCamUntriggerOnLastKeyDelay
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#numpos","title":"numPos
","text":"The number of position key frames for the camera animation.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#numtargets","title":"numTargets
","text":"The number of target key frames for the camera animation.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#paused","title":"paused
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#started","title":"started
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#gototimemode","title":"gotoTimeMode
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#cstime","title":"csTime
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
A list of position key frames. The number of items is indicated by the numPos
property.\u00a0\u21a9\u21a9\u21a9\u21a9
A list of target key frames. The number of items is indicated by the numTargets
property.\u00a0\u21a9\u21a9\u21a9\u21a9
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/","title":"zCCamTrj_KeyFrame","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#zccamtrj_keyframe","title":"zCCamTrj_KeyFrame","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCCamTrj_KeyFrame
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#time","title":"time
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#anglerolldeg","title":"angleRollDeg
","text":"The camera rotation angle of the frame along the Z axis.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#camfovscale","title":"camFOVScale
","text":"Focal zoom of the camera's field of view (FOV) of the frame. Use reasonable values to avoid dizzying effects.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontype","title":"motionType
","text":"The type of camera movement for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontypefov","title":"motionTypeFOV
","text":"The type of focus change for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontyperoll","title":"motionTypeRoll
","text":"The type of rotation for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontypetimescale","title":"motionTypeTimeScale
","text":"Unclear.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#tension","title":"tension
","text":"Defines the bend of the camera motion curve at the specified key. Larger values result in a sharper bend.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#bias","title":"bias
","text":"Determines the slope of a line in one direction. The direction of the slope is determined by the sign, and the steepness by the value.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#continuity","title":"continuity
","text":"Determines the amount of curve discontinuity at this animation key.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#timescale","title":"timeScale
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#timeisfixed","title":"timeIsFixed
","text":"An auxiliary flag indicating the time of the key frame, which cannot be changed automatically.
Accepted values:
TRUE
\u2014 The time of this frame is set manually and cannot be changed automatically. FALSE
\u2014 The frame time is calculated from the total specified animation playback time. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#originalpose","title":"originalPose
","text":"Unknown.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/","title":"zCVobLevelCompo","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/#zcvoblevelcompo","title":"zCVobLevelCompo","text":"Quick Infos
Class Name: zCVobLevelCompo
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Used as root objects of game levels. Only used to group together other VObjects. Only one of the zCVobLevelCompo
objects will have a visual which corresponds to the mesh of the world it exists in. Generally, it can be ignored and has no relevance to other VObjects in the hierarchy.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/","title":"zCVobLight","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#zcvoblight","title":"zCVobLight","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCVobLight
Version Identifiers: \u2014 Gothic I: 46080
\u2014 Gothic II: 39168
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents a virtual light source which lights up nearby game objects. Point and spot light sources are supported and may be animated with different colors and ranges.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE canMove = FALSE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE canMove = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightpresetinuse","title":"lightPresetInUse
","text":"The name of the selected light template. Templates can be found in _work/data/Presets/LightPresets.zen
. This property is irrelevant for most use-cases.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lighttype","title":"lightType
","text":"The type of the light source.
Accepted values:
POINT
\u2014 A point light source. SPOT
\u2014 A spot light source. "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#range","title":"range
","text":"The range in which this light source illuminates objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#color","title":"color
","text":"The color of this light source in RGBA form.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#spotconeangle","title":"spotConeAngle
","text":"The angle of the beam cone for spotlights. Only relevant if lightType
is SPOT
, ignored otherwise.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightstatic","title":"lightStatic
","text":"Determines whether this is a static light or not. Static lights are baked into the world when its lighting is compiled. This makes static lights faster at runtime, but it also means, that they cannot change in any way after the world is compiled.
Accepted values:
TRUE
\u2014 This light is a static light. FALSE
\u2014 This light is a dynamic light. "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightquality","title":"lightQuality
","text":"Determines the quality of the light source. What exactly changes with these values is unknown.
Accepted values:
HIGH
\u2014 Highest quality. MEDIUM
\u2014 Medium quality. LOW_FASTEST
\u2014 Low quality (used for almost all lights). "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lensflarefx","title":"lensflareFX
","text":"The name of the lensflare effect associated with this light. Empty if there is no associated lensflare effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#turnedon","title":"turnedOn
","text":"Whether this dynamic light is turned on.
Accepted values:
TRUE
\u2014 The light is turned on. FALSE
\u2014 The light is turned off. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeaniscale","title":"rangeAniScale
","text":"Frames for the light's range animation. Its value is a space-separated list of floats where each float is one key frame of the animation. A value of 1.0
corresponds to the initial range
of the light source, a value of 2.0
corresponds to double the initial range
and a value of 0.5
means half the initial range
. The range animation is further controlled by rangeAniFPS
and rangeAniSmooth
.
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeanifps","title":"rangeAniFPS
","text":"The speed of the range animation in frames per second. The animation frames are defined in rangeAniScale
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeanismooth","title":"rangeAniSmooth
","text":"Whether the range animation should smoothly interpolate between keyframes.
Accepted values:
TRUE
\u2014 Turn on interpolation. FALSE
\u2014 Turn off interpolation. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranilist","title":"colorAniList
","text":"Frames for the light's color animation. Its value is a space-separated list of colors where each element can either be an RGB color consisting of three integers enclosed by parentheses or a greyscale color consisting of a single integer. For example: (255 0 0) 100 (255 50 180)
would result in #ff0000 #646464, #ff32b4. The color animation is further controlled by colorAniFPS
and colorAniSmooth
.
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranifps","title":"colorAniFPS
","text":"The speed of the color animation in frames per second. The animation frames are defined in colorAniList
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranismooth","title":"colorAniSmooth
","text":"Whether the color animation should smoothly interpolate between keyframes.
Accepted values:
TRUE
\u2014 Turn on interpolation. FALSE
\u2014 Turn off interpolation. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#canmove","title":"canMove
","text":"Unknown.
Warning
This value is only valid for dynamic lights in Gothic II. Check lightstatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/","title":"zCVobSpot","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/#zcvobspot","title":"zCVobSpot","text":"Quick Infos
Class Name: zCVobSpot
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Spot objects are used to mark a position and orientation in virtual space. They are equivalent in function to way net free points and can be used in scripts to spawn other objects at their location.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/","title":"zCVobStair","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/#zcvobstair","title":"zCVobStair","text":"Quick Infos
Class Name: zCVobStair
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: Unused Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Used to mark staircase models in Gothic I only. This type of VObject was taken into account by the NPC pathfinding routines to properly ascend and descend staircases.
Warning
This VObject is only available in Gothic I.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) Unavailable.
Unavailable.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/","title":"zCVobStartpoint","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/#zcvobstartpoint","title":"zCVobStartpoint","text":"Quick Infos
Class Name: zCVobStartpoint
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Marks the players initial position when loading in the game level. Behaves like zCVobSpot
but causes the game to put the player at its location and in its orientation when the world is loaded.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/","title":"zCVobWaypoint","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/#zcvobwaypoint","title":"zCVobWaypoint","text":"Quick Infos
Class Name: zCVobWaypoint
Version Identifiers: \u2014 Gothic I: Unknown \u2014 Gothic II: Unknown Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
Waypoints are used to mark a position and orientation in virtual space like zCVobSpot
, but are combined into a path network through which NPCs will perform pathfinding. Waypoints can be used in scripts to spawn other objects at their location.
Warning
zCVobWaypoint
objects aren't saved in .ZEN
files. Their zCWaypoint
representations are used instead.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/#class-members","title":"Class members","text":"Gothic 1Gothic 2 "},{"location":"zengin/worlds/Classes/zCVob/oCVob/","title":"oCVob","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/#ocvob","title":"oCVob","text":"Quick Infos
Class Name: oCVob
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: Unused Sources: \u2014 zk.gothickit.dev
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/","title":"oCItem","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#ocitem","title":"oCItem","text":"Quick Infos
Class Name: oCItem
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents an item in the game world. Items are special VObjects which are tied to a script instance which defines their attributes. They have physics enabled and can be targeted and picked up by the player.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCItem itemInstance = \"\" amount = 0 flags = 0 zCVob oCVob oCItem itemInstance = \"\" amount = 0 flags = 0 "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#iteminstance","title":"itemInstance
","text":"The name of the script instance representing the item.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#amount","title":"amount
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#flags","title":"flags
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/","title":"oCMOB","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#ocmob","title":"oCMOB","text":"Quick Infos
Class Name: oCMOB
Version Identifiers: \u2014 Gothic I: 47105
\u2014 Gothic II: 47105
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which can optionally be moved and/or carried.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#focusname","title":"focusName
","text":"The name of the object as seen in-game when focusing it.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#hitpoints","title":"hitpoints
","text":"The number of hitpoints of the object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#damage","title":"damage
","text":"The damage dealt by the object when being used.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#moveable","title":"moveable
","text":"Whether the object can be moved by the player.
Accepted values:
TRUE
\u2014 The object can be moved FALSE
\u2014 The object can not be moved "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#takeable","title":"takeable
","text":"Whether the object can be carried by the player.
Accepted values:
TRUE
\u2014 The object can be carried FALSE
\u2014 The object can not be carried "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#focusoverride","title":"focusOverride
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#soundmaterial","title":"soundMaterial
","text":"The sound to play when the object is hit.
Accepted values:
WOOD
\u2014 Wood. STONE
\u2014 Stone. METAL
\u2014 Metal. LEATHER
\u2014 Leather. CLAY
\u2014 Clay. GLAS
\u2014 Glass. "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#visualdestroyed","title":"visualDestroyed
","text":"The name of the visual to use when the object is destroyed. Behaves like zCVob.visual.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#owner","title":"owner
","text":"The name of the script instance of the NPC who is the owner of this object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#ownerguild","title":"ownerGuild
","text":"The name of the guild this object belongs to. This name corresponds to the script constant for each guild (i.e. GIL_BAU
), found in Constants.d
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#isdestroyed","title":"isDestroyed
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/","title":"oCMobInter","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#ocmobinter","title":"oCMobInter","text":"Quick Infos
Class Name: oCMobInter
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Interactive objects can be interacted with by NPCs and the player. Every time the object is interacted with, an OnTrigger
event is sent to the triggerTarget
object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#statenum","title":"stateNum
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#triggertarget","title":"triggerTarget
","text":"The name of the VObject(s) to send an OnTrigger
event to when this object is interacted with. Controlled by the rewind
property.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#usewithitem","title":"useWithItem
","text":"The name of the item which the player or NPC must have in their inventory in order to interact with the object. Corresponds to the name of the item instance in the scripts.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#conditionfunc","title":"conditionFunc
","text":"The name of a script function which, when called, determines whether the object can be interacted with. The script function returns an int which is either 0
, if the object should be disabled and 1
if it should be enabled.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#onstatefunc","title":"onStateFunc
","text":"The name of a script function to be called when the object is being used.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#rewind","title":"rewind
","text":"Determines whether an OnTrigger
event should be sent every time the object is interacted with or only the first time.
Accepted values:
TRUE
\u2014 Send OnTrigger
events multiple times FALSE
\u2014 Only send the event once "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/","title":"oCMobBed","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/#ocmobbed","title":"oCMobBed","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: oCMobBed
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
VObject marking beds for NPCs and the player to sleep on. In the original Gothic I, there is a bug which prevents oCMobBed
s from working correctly, so it is recommended to instead use oCMobDoor
and attach the visual of a bed when targeting that platform.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/","title":"oCMobFire","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#ocmobfire","title":"oCMobFire","text":"Quick Infos
Class Name: oCMobFire
Version Identifiers: \u2014 Gothic I: 18433
\u2014 Gothic II: 18433
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
An object with an integrated fire effect. Only supports rigged models as visuals.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#fireslot","title":"fireSlot
","text":"The bone of the rigged model to place the fire effect at.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#firevobtreename","title":"fireVobtreeName
","text":"The name of the template file which contains the configuration of the fire effect. For example: FIRETREE_MEDIUM.ZEN
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/","title":"oCMobLadder","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/#ocmobladder","title":"oCMobLadder","text":"Quick Infos
Class Name: oCMobLadder
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject representing a ladder. NPCs can interact with ladders by climbing.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/","title":"oCMobSwitch","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/#ocmobswitch","title":"oCMobSwitch","text":"Quick Infos
Class Name: oCMobSwitch
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A VObject representing a switch with two states.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/","title":"oCMobWheel","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/#ocmobwheel","title":"oCMobWheel","text":"Quick Infos
Class Name: oCMobWheel
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A wheel with four different states. For example, this is used for the gates of the old camp in Gothic I.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/","title":"oCMobLockable","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#ocmoblockable","title":"oCMobLockable","text":"Quick Infos
Class Name: oCMobLockable
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many lockable objects like containers and doors.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#locked","title":"locked
","text":"Determines whether the container is locked.
Accepted values:
TRUE
\u2014 The container is locked FALSE
\u2014 The container is not locked "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#keyinstance","title":"keyInstance
","text":"The name of the item script instance which unlocks the container.
Tip
Only relevant if the container is locked.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#picklockstr","title":"pickLockStr
","text":"The combination which unlocks this container when picking the lock. Each character of the string is either R
or L
where R
stands for \"Right\" and L
stands for \"Left\". If empty, the lock can not be picked. Example: LRRLLRL
.
Tip
Only relevant if the container is locked.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/","title":"oCMobContainer","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#ocmobcontainer","title":"oCMobContainer","text":"Quick Infos
Class Name: oCMobContainer
Version Identifiers: \u2014 Gothic I: 64513
\u2014 Gothic II: 64513
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
An object which contains items.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer Container NumOfEntries = 0 oCItem ... = NULL zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer Container NumOfEntries = 0 oCItem ... = NULL "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#contains","title":"contains
","text":"The items found inside the container as a comma-separated list. Each element of the list starts with the name of the item script instance and is optionally followed by a colon and a number, indicating the number of that item to be found inside. Example: ItMi_Gold:75, ItFo_Fish:2, ItMi_Quartz
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#numofentries","title":"NumOfEntries
","text":"The number of items in the container.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/","title":"oCMobDoor","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/#ocmobdoor","title":"oCMobDoor","text":"Quick Infos
Class Name: oCMobDoor
Version Identifiers: \u2014 Gothic I: 64513
\u2014 Gothic II: 64513
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject representing a door. This is also used for NPCs navigating the waynet.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/","title":"zCEffect","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/#zceffect","title":"zCEffect","text":"Quick Infos
Class Name: zCEffect
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many visual and sound effects.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/","title":"zCEarthquake","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#zcearthquake","title":"zCEarthquake","text":"Quick Infos
Class Name: zCEarthquake
Version Identifiers: \u2014 Gothic I: Unused \u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to create an earthquake effect when it receives an OnTrigger
event. An earthquake is represented by a shaking camera.
Warning
This VObject is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) Unavailable
zCVob zCEffect zCEarthquake Earthquake radius = 200 timeSec = 5 amplitudeCM = 0 Unavailable
zCVob zCEffect zCEarthquake Earthquake radius = 200 timeSec = 5 amplitudeCM = 0 "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#radius","title":"radius
","text":"The radius of the earthquake effect
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#timesec","title":"timeSec
","text":"The duration of the earthquake effect in seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#amplitudecm","title":"amplitudeCM
","text":"The amplitude of the earthquake effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/","title":"zCPFXController","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#zcpfxcontroller","title":"zCPFXController","text":"Quick Infos
Class Name: zCPFXControler
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A particle system in virtual space. Its effect can be activated and deactivated using the OnTrigger
and OnUntrigger
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#pfxname","title":"pfxName
","text":"The name of the particle effect. Corresponds to a .ZEN
file containing the particle system definition.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#killvobwhendone","title":"killVobWhenDone
","text":"Disable the particle effect after it runs once.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#pfxstarton","title":"pfxStartOn
","text":"Whether to start the particle effect when the level is loaded.
Accepted values:
TRUE
\u2014 Start the particle effect when loading the world. FALSE
\u2014 Don't start the particle effect automatically. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/","title":"zCVobAnimate","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#zcvobanimate","title":"zCVobAnimate","text":"Quick Infos
Class Name: zCVobAnimate
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to create animated models. The visual of such objects can either be a morph mesh or a model with a skeletal animation (i.e. a model script). The animation of these objects can be started and stopped using OnTrigger
and OnUntrigger
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobAnimate zCVob zCEffect zCVobAnimate zCVob zCEffect zCVobAnimate startOn = \"\" isRunning = FALSE zCVob zCEffect zCVobAnimate startOn = \"\" isRunning = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#starton","title":"startOn
","text":"Whether to start this animation when loading the level.
Accepted values:
TRUE
\u2014 Immediately start the animation when the level is loaded. FALSE
\u2014 Don't automatically start the animation. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#isrunning","title":"isRunning
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/","title":"zCVobLensFlare","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#zcvoblensflare","title":"zCVobLensFlare","text":"Quick Infos
Class Name: zCVobLensFlare
Version Identifiers: \u2014 Gothic I: 64704
\u2014 Gothic II: 193
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents a lens flare effect. Behaves exactly like the base zCVob
but has a lens flare effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#lensflarefx","title":"lensflareFX
","text":"The name of the lens flare effect. Must be one of the effects listed in /_work/data/Presets/Lensflare.zen
.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/","title":"zCVobScreenFX","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/#zcvobscreenfx","title":"zCVobScreenFX","text":"Quick Infos
Class Name: zCVobScreenFX
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Screen effect VObjects are used to create special effects. They are used for field-of-view changes, adding black bars for a cinematic feel to the game and other post-processing effects.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/","title":"zCTouchAnimate","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#zctouchanimate","title":"zCTouchAnimate","text":"Quick Infos
Class Name: zCTouchAnimate
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 20483
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
A VObject that plays its animation when it receives an OnTick
event (basically when something touches it).
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#presentation","title":"Presentation","text":"Following video shows the behaviour of this VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/","title":"zCTouchAnimateSound","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#zctouchanimatesound","title":"zCTouchAnimateSound","text":"Quick Infos
Class Name: zCTouchAnimateSound
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 20483
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
Object similar to zCTouchAnimate
, but allowing to specify a sound that plays on the event activation.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#sfxtouch","title":"sfxTouch
","text":"The name of the sound produced upon contact with an object.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#presentation","title":"Presentation","text":"Following video shows the behaviour of this VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/","title":"zCTouchDamage","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#zctouchdamage","title":"zCTouchDamage","text":"Quick Infos
Class Name: zCTouchDamage
Version Identifiers: \u2014 Gothic I: 36865
\u2014 Gothic II: 36865
Source: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which damages other VObjects colliding with it.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damage","title":"damage
","text":"The amount of damage being dealt.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#barrier","title":"Barrier
","text":"Accepted values:
TRUE
\u2014 Deal barrier damage FALSE
\u2014 Do not deal barrier damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#blunt","title":"Blunt
","text":"Accepted values:
TRUE
\u2014 Deal blunt damage (blunt weapons) FALSE
\u2014 Do not deal blunt damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#edge","title":"Edge
","text":"Accepted values:
TRUE
\u2014 Deal edge damage (sharp weapons) FALSE
\u2014 Do not deal edge damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fire","title":"Fire
","text":"Accepted values:
TRUE
\u2014 Deal fire damage FALSE
\u2014 Do not deal fire damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fly","title":"Fly
","text":"Accepted values:
TRUE
\u2014 Deal knockout damage FALSE
\u2014 Do not deal knockout damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#magic","title":"Magic
","text":"Accepted values:
TRUE
\u2014 Deal magic damage FALSE
\u2014 Do not deal magic damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#point","title":"Point
","text":"Accepted values:
TRUE
\u2014 Deal point damage (bows and crossbows) FALSE
\u2014 Do not deal point damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fall","title":"Fall
","text":"Accepted values:
TRUE
\u2014 Deal fall damage FALSE
\u2014 Do not deal fall damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagerepeatdelaysec","title":"damageRepeatDelaySec
","text":"The delay between damage ticks when applying continuous damage. If set to 0
, only deals the damage once per collision. If set to a value greater than 0
, deals damage every damageRepeatDelaySec
seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagevoldownscale","title":"damageVolDownScale
","text":"A scale value used in conjunction with damageCollType
. Its function depends on the type of collision detection used.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagecolltype","title":"damageCollType
","text":"The type of collision detection to use for damage calculations.
Accepted values:
NONE
\u2014 Disable collision detection and thus damage application. BOX
\u2014 Scale the bbox3dws
of the zCTouchDamage
object by damageVolDownScale
and use this new bounding box to calculate collisions with other VObjects POINT
\u2014 Scale the bbox3dws
of the colliding object by damageVolDownScale
and only deal damage if it contains the center point of the zCTouchDamage
object. If the visual
of the zCTouchDamage
object is a particle effect, test against every particle instead. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/","title":"oCTouchDamage","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/#octouchdamage","title":"oCTouchDamage","text":"Quick Infos
Class Name: oCTouchDamage
Version Identifiers: \u2014 Gothic I: 36865
\u2014 Gothic II: 36865
Sources: \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/","title":"zCTriggerBase","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#zctriggerbase","title":"zCTriggerBase","text":"Quick Infos
Class Name: zCTriggerBase
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many triggers.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#triggertarget","title":"triggerTarget
","text":"The name of VObject to send OnTrigger
and OnUntrigger
events to after processing.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/","title":"zCCodeMaster","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#zccodemaster","title":"zCCodeMaster","text":"Quick Infos
Class Name: zCCodeMaster
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Source: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
zCCodeMaster
VObjects keep a list of 'slave' VObjects and keep track of events received by them. If the master receives an OnTrigger
event from a slave, it remembers that it did. After it has receives an OnTrigger
message from all slaves, it emits an OnTrigger
event to the triggerTarget
. Receiving or sending an OnTrigger
event is also referred to as an 'activation' for this purpose.
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" numSlavesTriggered = 0 slaveTriggered ... = NULL "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#orderrelevant","title":"orderRelevant
","text":"Controls whether the master should keep track of the order it receives messages from its slaves.
Accepted values:
TRUE
\u2014 Only send an OnTrigger
event to the triggerTarget
if the slaves have fired in the exact order they are configured here. Also counts multiple activations. FALSE
\u2014 Send an OnTrigger
event to the triggerTarget
after all slaves have fired at least once, regardless of order. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#firstfalseisfailure","title":"firstFalseIsFailure
","text":"Controls when the slave activation sequence is considered to be incorrect. After the sequence is marked as incorrect an OnTrigger
event is sent to triggerTargetFailure
.
Accepted values:
TRUE
\u2014 The sequence is considered to be incorrect as soon as one slave is activated out-of-order. FALSE
\u2014 The sequence is considered to be incorrect only after all slaves have been activated at least once and they were activated out-of-order. Warning
Only relevant if orderRelevant
is set to TRUE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#triggertargetfailure","title":"triggerTargetFailure
","text":"The name of the VObject to emit an OnTrigger
event to if the activation sequence fails. This is controlled by firstFalseIsFailure
.
Warning
Only relevant if orderRelevant
is set to TRUE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#untriggercancels","title":"untriggerCancels
","text":"Controls whether slaves can emit OnUntrigger
events to the master VObject to mark themselves as deactivated.
Accepted values:
TRUE
\u2014 When the master receives an OnUntrigger
event from the slave, it marks it as not having been activated. FALSE
\u2014 The master ignore OnUntrigger
events from its slaves. Warning
Only relevant if orderRelevant
is set to FALSE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#slavevobname","title":"slaveVobName
","text":"The name of a slave VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#numslavestriggered","title":"numSlavesTriggered
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/","title":"zCMessageFilter","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#zcmessagefilter","title":"zCMessageFilter","text":"Quick Infos
Class Name: zCMessageFilter
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
Transforms any incoming OnTrigger
and OnUntrigger
events before passing them on to the trigger target. All OnTrigger
and OnUntrigger
messages received by this zCMessageFilter
VObject are transformed according to onTrigger
and onUntrigger
and then passed on to the VObject with the name specified in the triggerTarget
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#ontrigger","title":"onTrigger
","text":"The type of event to emit to the triggerTarget
if this VObject receives an OnTrigger
message.
Accepted values:
MT_NONE
\u2014 Don't emit another event. MT_TRIGGER
\u2014 Emit an OnTrigger
event. MT_UNTRIGGER
\u2014 Emit an OnUntrigger
event. MT_ENABLE
\u2014 Emit an Enable
event. MT_DISABLE
\u2014 Emit a Disable
event. MT_TOGGLE_ENABLED
\u2014 Emit a ToggleEnabled
event. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#onuntrigger","title":"onUntrigger
","text":"The type of event to emit to the triggerTarget
if this VObject receives an OnUntrigger
message.
Accepted values:
MT_NONE
\u2014 Don't emit another event. MT_TRIGGER
\u2014 Emit an OnTrigger
event. MT_UNTRIGGER
\u2014 Emit an OnUntrigger
event. MT_ENABLE
\u2014 Emit an Enable
event. MT_DISABLE
\u2014 Emit a Disable
event. MT_TOGGLE_ENABLED
\u2014 Emit a ToggleEnabled
event. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/","title":"zCMoverControler","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#zcmovercontroler","title":"zCMoverControler","text":"Quick Infos
Class Name: zCMoverControler
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to control zCMover
objects of type NSTATE_SINGLE_KEYS
specifically. zCMoverControler
objects react to incoming OnTrigger
events to send a pre-configured event to the target mover object named by the triggerTarget
propery, controlling its animation. Mover controllers can make movers go to a specific keyframe in their animation or just step one keyframe back and forth at a time.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#movermessage","title":"moverMessage
","text":"The type of event to emit to the triggerTarget
when this controller receives an OnTrigger
event.
Accepted values:
GOTO_KEY_FIXED_DIRECTLY
\u2014 Make the target mover directly go to the keyframe specified in gotoFixedKey
, skipping all intermediate keyframes. GOTO_KEY_FIXED_ORDER
\u2014 Make the target mover go to the keyframe specified in in gotoFixedKey
while still going through all intermediate keyframes. GOTO_KEY_NEXT
\u2014 Make the target mover go to the next keyframe in sequence. Wraps around to the first keyframe. GOTO_KEY_PREV
\u2014 Make the target mover go to the previous keyframe in sequence. Wraps around to the last keyframe. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#gotofixedkey","title":"gotoFixedKey
","text":"The keyframe of the mover referred to by triggerTarget
to move to.
Warning
Only relevant if moverMessage
is GOTO_KEY_FIXED_DIRECTLY
or GOTO_KEY_FIXED_ORDER
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/","title":"zCTriggerUntouch","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/#zctriggeruntouch","title":"zCTriggerUntouch","text":"Quick Infos
Class Name: zCTriggerUntouch
Version Identifiers: \u2014 Gothic I: 52224
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A trigger which fires an OnTrigger
event to its triggerTarget
if any OnUntouch
event is emitted from an inanimate object within the object's bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/","title":"zCTriggerWorldStart","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#zctriggerworldstart","title":"zCTriggerWorldStart","text":"Quick Infos
Class Name: zCTriggerWorldStart
Version Identifiers: \u2014 Gothic I: 52224
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special trigger which fires an OnTrigger
event to its triggerTarget
when the world is loaded and started.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#fireonlyfirsttime","title":"fireOnlyFirstTime
","text":"Determines whether to fire the OnTrigger
event only the first time the world is loaded.
Accepted values:
TRUE
\u2014 Only fire the event if this is the first time the world is loaded. FALSE
\u2014 Fire the event every time the world is loaded. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/","title":"zCTrigger","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#zctrigger","title":"zCTrigger","text":"Quick Infos
Class Name: zCTrigger
Version Identifiers: \u2014 Gothic I: 47105
\u2014 Gothic II: 47105
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
VObject to process and relay specific filtered events. When a zCTrigger
receives an OnTrigger
, OnDamage
, or OnTouch
event it checks whether the event source (an oCNpc
, the player or another VObject) should be acknowledged (see respondToNPC
, respondToPC
and respondToObject
respectively). It then verifies if it should react to the specific event by checking the reactToOnTrigger
, reactToOnDamage
and reactToOnTouch
properties. If both checks succeed, an OnTrigger
event is sent to the triggerTarget
and the trigger is considered to be activated. zCTrigger
objects can be enabled and disabled by firing OnEnable
, OnDisable
and OnToggleEnabled
events at them.
Tip
The respondTo{Object,PC,NPC,VobName}
properties are logically linked by and \"or\" expression.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE nextTimeTriggerable = 0.0 savedOtherVob = NULL countCanBeActivated zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE nextTimeTriggerable = 0.0 savedOtherVob = NULL countCanBeActivated = 0 isEnabled = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoontrigger","title":"reactToOnTrigger
","text":"Whether this trigger should react to OnTrigger
events.
Accepted values:
TRUE
\u2014 Do react to OnTrigger
events by sending an OnTrigger
message to the triggerTarget
If sendUntrigger
is set to TRUE
, also sends an OnUntrigger
event to the triggerTarget
if the trigger receives an OnUntrigger
event. FALSE
\u2014 Ignore OnTrigger
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoontouch","title":"reactToOnTouch
","text":"Whether this trigger should react to OnTouch
events.
Accepted values:
TRUE
\u2014 Do react to OnTouch
events by sending an OnTrigger
message to the triggerTarget
If sendUntrigger
is set to TRUE
, also sends an OnUntrigger
event to the triggerTarget
if the trigger receives an OnUntouch
event. FALSE
\u2014 Ignore OnTouch
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoondamage","title":"reactToOnDamage
","text":"Whether this trigger should react to OnDamage
events.
Accepted values:
TRUE
\u2014 Do react to OnDamage
events by sending an OnTrigger
message to the triggerTarget
FALSE
\u2014 Ignore OnDamage
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtoobject","title":"respondToObject
","text":"Whether this trigger should process events coming from inanimate objects.
Accepted values:
TRUE
\u2014 Do process events from inanimate objects. FALSE
\u2014 Ignore events from inanimate objects. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtopc","title":"respondToPC
","text":"Whether this trigger should process events coming from the player.
Accepted values:
TRUE
\u2014 Do process events from the player. FALSE
\u2014 Ignore events from the player. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtonpc","title":"respondToNPC
","text":"Whether this trigger should process events coming from NPCs.
Accepted values:
TRUE
\u2014 Do process events from NPCs. FALSE
\u2014 Ignore events from NPCs. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#startenabled","title":"startEnabled
","text":"Determines whether the trigger is initially enabled. Enabled triggers will process incoming events and send outgoing events while disabled triggers do not. Triggers can be activated and deactivated at runtime by sending them OnEnable
, OnDisable
or OnToggleEnabled
events.
Accepted values:
TRUE
\u2014 Enable the trigger when the world is loaded. FALSE
\u2014 Do not enable the trigger when the world is loaded. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtovobname","title":"respondToVobName
","text":"Whether this trigger should process events coming from VObjects with this name. If empty, match no VObject name directly.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#numcanbeactivated","title":"numCanBeActivated
","text":"The number of times the trigger will process incoming events. If set to -1
the trigger will process an infinite number of events.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#retriggerwaitsec","title":"retriggerWaitSec
","text":"The number of seconds that have to elapse after processing an event before the trigger will process additional events. All events received by the trigger during that time are ignored.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#damagethreshold","title":"damageThreshold
","text":"The amount of damage which must be dealt for the trigger to react to an OnDamage
event.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#firedelaysec","title":"fireDelaySec
","text":"The number of seconds to wait before emitting the OnTrigger
event after processing.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#senduntrigger","title":"sendUntrigger
","text":"Whether to send and OnUntrigger
event to the triggerTarget
after the trigger receives an OnUntrigger
or OnUntouch
event. Only fires the OnUntrigger
event if reactToOnTrigger
and reactToOnTouch
are set to TRUE
respectively.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#nexttimetriggerable","title":"nextTimeTriggerable
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#savedothervob","title":"savedOtherVob
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#countcanbeactivated","title":"countCanBeActivated
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#isenabled","title":"isEnabled
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/","title":"oCCSTrigger","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/#occstrigger","title":"oCCSTrigger","text":"Quick Infos
Class Name: oCCSTrigger
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A special trigger VObject which can start a cutscene. The triggerTarget
must be the name of the cutscene (without the extension) to be started. For this to work, the cutscene must already be loaded. OnUntrigger
events are ignored by oCCSTrigger
s.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/","title":"oCTriggerChangeLevel","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#octriggerchangelevel","title":"oCTriggerChangeLevel","text":"Quick Infos
Class Name: oCTriggerChangeLevel
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special zCTrigger
which in addition to performing all other trigger actions also causes the engine to load another level when activated.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#levelname","title":"levelName
","text":"The name of the level to load including the file extension.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#startvobname","title":"startVobName
","text":"The name of the VObject in the new level to place the player at.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/","title":"oCTriggerScript","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#octriggerscript","title":"oCTriggerScript","text":"Quick Infos
Class Name: oCTriggerScript
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special zCTrigger
which in addition to performing all other trigger actions also calls a script function when the trigger is activated. OnUntrigger
events do not result in the script function being called.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#scriptfunc","title":"scriptFunc
","text":"The name script function to call when the trigger successfully processes a message.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/","title":"zCMover","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#zcmover","title":"zCMover","text":"Quick Infos
Class Name: zCMover
Version Identifiers: \u2014 Gothic I: 39936
\u2014 Gothic II: 39936
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which can move along a pre-determined path in response to an event. Movers can be controlled through a set of keyframes or the animation of their visuals. If the visual has an attached animation to be used as the mover's animation, it must have the following animations which are run depending on the mover's state: S_OPEN
, S_CLOSED
, T_CLOSED_2_OPEN
, T_OPEN_2_CLOSED
, S_LOCKED
, S_UNLOCKED
, T_UNLOCKED_TO_LOCKED
, T_LOCKED_TO_UNLOCKED
.
Each mover is in one of three states, \"open\", \"closed\" or \"moving\". Keyframe 0
(or S_OPEN
when using the visual's animation) corresponds to the \"open\" state while the last keyframe (or S_CLOSED
) corresponds to the \"closed\" state. When transitioning between the \"open\" and \"closed\" states, the mover is in the \"moving\" state during which it sequentially moves between its keyframes (or runs the T_CLOSED_2_OPEN
or T_OPEN_TO_CLOSED
animations). Movers with their moverBehavior
set to NSTATE_SINGLE_KEYS
are an exception to this rule: each keyframe can individually be addressed as a state.
Movers are specialized triggers. Before beginning their animation, movers first filter the incoming events as per the zCTrigger
's rules and only start the animation if the event passes through the filters. When the mover reaches the \"open\" state after being activated, it emits an OnTrigger
event according to the fire behavior set for the zCTrigger
. Similarly, when it reaches the \"closed\" state it emits an OnUntrigger
event.
Movers can be enabled and disabled using the OnEnable
, OnDisable
and OnToggleDisabled
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE autoRotate = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST actKeyPosDelta = 0 0 0 actKeyframeF = 0.0 actKeyframe = 0 nextKeyframe = 0 moveSpeedUnit = 0.0 advanceDir = 0.0 moverState = ? numTriggerEvents = 0 stayOpenTimeDest = 0.0 Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE autoRotate = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST actKeyPosDelta = 0 0 0 actKeyframeF = 0.0 actKeyframe = 0 nextKeyframe = 0 moveSpeedUnit = 0.0 advanceDir = 0.0 moverState = ? numTriggerEvents = 0 stayOpenTimeDest = 0.0 Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverbehavior","title":"moverBehavior
","text":"Controls how the mover behaves in response to events (\"activation\").
Accepted values:
2STATE_TOGGLE
\u2014 Receiving either event causes the state of the mover to swap. The direction of the animation is reversed. 2STATE_TRIGGER_CTRL
\u2014 An OnTrigger
causes the mover to transition to the \"open\" state while an OnUntrigger
event causes the mover to transition to the \"closed\" state. 2STATE_OPEN_TIMED
\u2014 An OnTrigger
event causes the mover to transition to the \"open\" state. It than transitions to the \"closed\" state after a fixed amount of time specified by stayOpenTimeSec
. NSTATE_LOOP
\u2014 The mover opens and closes in a loop indefinitely. NSTATE_SINGLE_KEYS
\u2014 The mover can transition to each keyframe separately. Often used in conjunction with a zCMoverControler
. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#touchblockerdamage","title":"touchBlockerDamage
","text":"The amount of damage to deal to objects in the way of the mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#stayopentimesec","title":"stayOpenTimeSec
","text":"The number of seconds a mover with the 2STATE_OPEN_TIMED
behavior stays in the \"open\" state until transitioning to the \"closed\" state again.
Warning
Only relevant if moverBehavior
is 2STATE_OPEN_TIMED
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverlocked","title":"moverLocked
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#autolinkenabled","title":"autoLinkEnabled
","text":"Determines whether the position of the object triggering the mover should be tied to the mover's position.
Accepted values:
TRUE
\u2014 When the mover transitions, the position of the triggering object follows the position of the mover. FALSE
\u2014 The triggering object's position is uncoupled from the position of the mover. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#autorotate","title":"autoRotate
","text":"Whether to automatically rotate the mover along its movement trajectory. For example, this is used for making fish always face in the direction they're moving.
Accepted values:
TRUE
\u2014 Automatically face the mover forward along its trajectory. FALSE
\u2014 Never automatically rotate the mover. Warning
Only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#numkeyframes","title":"numKeyframes
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#movespeed","title":"moveSpeed
","text":"The movement speed for transitioning between keyframes in units per millisecond.
Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#poslerptype","title":"posLerpType
","text":"Defines how the mover should interpolate between the keyframe positions. Only affects the mover's position, never its rotation.
Accepted values:
CURVE
\u2014 Smoothly transition between keyframes. LINEAR
\u2014 Linearly transition between keyframes. Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#speedtype","title":"speedType
","text":"Controls the acceleration and deceleration behavior of the mover.
Accepted values:
CONST
\u2014 Mover with a constant speed. SLOW_START_END
\u2014 Slowly accelerate at the first keyframe and decelerate at the last keyframe. SLOW_START
\u2014 Slowly accelerate at the first keyframe but don't decelerate at the end. SLOW_END
\u2014 Slowly decelerate at the last keyframe but don't accelerate at the start. SEG_SLOW_START_END
\u2014 Slowly accelerate at the beginning of each keyframe and decelerate at the end of each keyframe. SEG_SLOW_START
\u2014 Slowly accelerate at the beginning of each keyframe but don't decelerate at the end. SEG_SLOW_END
\u2014 Slowly decelerate at the end of each keyframe but don't accelerate at the beginning. Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxopenstart","title":"sfxOpenStart
","text":"The name of the sound to play at the beginning of the opening sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxopenend","title":"sfxOpenEnd
","text":"The name of the sound to play at the end of the opening sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxmoving","title":"sfxMoving
","text":"The name of the sound to play in a loop while the mover is transitioning between keyframes.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxclosestart","title":"sfxCloseStart
","text":"The name of the sound to play at the beginning of the closing sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxcloseend","title":"sfxCloseEnd
","text":"The name of the sound to play at the end of the closing sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxlock","title":"sfxLock
","text":"The name of the sound to play when locking a mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxunlock","title":"sfxUnlock
","text":"The name of the sound to play when unlocking a mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxuselocked","title":"sfxUseLocked
","text":"The name of the sound to play when using a locked mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyposdelta","title":"actKeyPosDelta
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyframef","title":"actKeyframeF
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyframe","title":"actKeyframe
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#nextkeyframe","title":"nextKeyframe
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#movespeedunit","title":"moveSpeedUnit
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#advancedir","title":"advanceDir
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverstate","title":"moverState
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#numtriggerevents","title":"numTriggerEvents
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#stayopentimedest","title":"stayOpenTimeDest
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/","title":"zCTriggerList","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#zctriggerlist","title":"zCTriggerList","text":"Quick Infos
Class Name: zCTriggerList
Version Identifiers: \u2014 Gothic I: 59776
\u2014 Gothic II: 5505
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A special trigger which emits the OnTrigger
events emitted by the zCTrigger
to multiple targets. How the events are sent can be configured through listProcess
. The triggerTarget
and fireDelaySec
properties of zCTrigger
should be ignored.
OnUntrigger
events sent to the trigger list are propagated to all targets in the list.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 actTarget = 0 sendOnTrigger = TRUE zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 actTarget = 0 sendOnTrigger = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#listprocess","title":"listProcess
","text":"Controls how events are sent to the targets.
Accepted values:
LP_ALL
\u2014 Every target in the trigger list is sent the OnTrigger
event sequentially. The fireDelay
of each target is taken into account so that target n
is fired after sum(fireDelay0, ..., fireDelayN-1)
seconds. LP_NEXT_ONE
\u2014 The event is sent to the next target in the list. LP_RAND_ONE
\u2014 The event is sent to a random target in the list. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#triggertarget","title":"triggerTarget
","text":"The name of the VObject to send events to. Behaves like triggerTarget
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#firedelay","title":"fireDelay
","text":"The delay after which to fire the event to the target. Behaves like fireDelaySec
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#acttarget","title":"actTarget
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#sendontrigger","title":"sendOnTrigger
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/","title":"zCTriggerTeleport","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#zctriggerteleport","title":"zCTriggerTeleport","text":"Quick Infos
Class Name: zCTriggerTeleport
Version Identifiers: \u2014 Gothic I: 59776
\u2014 Gothic II: 45570
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
This VObject allows teleporting a hero to the waypoint.
Note
To make trigger work, you must set the value of the cdDyn
parameter to True
and specify the Waypoint in triggerTarget
parameter.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#sfxteleport","title":"sfxTeleport
","text":"Sound accompaniment of character teleport.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/","title":"zCZone","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/#zczone","title":"zCZone","text":"Quick Infos
Class Name: zCZone
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for effect zones.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/","title":"oCZoneMusic","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#oczonemusic","title":"oCZoneMusic","text":"Quick Infos
Class Name: oCZoneMusic
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the music to be played within its bounding box. Music zones may overlap; if they do, their priority
property determines which music zone should be used. The camera object is used to test which music zone applies. If no music zone applies the music defined in the optional oCZoneMusicDefault
is used.
The name of the music theme to be played is defined by the vobName
. Notice that end of the name is taken as a C_MUSICTHEME prefix. For example zone OLDCAMP_OC
will play theme starting with OC_
.
Tip
If the suffix _NCI
or _NCO
is added to the end of the zone name, it snows instead of rains in the zone.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE local_enabled = FALSE dayEntranceDone = FALSE nightEntranceDone = FALSE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE local_enabled = FALSE dayEntranceDone = FALSE nightEntranceDone = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#enabled","title":"enabled
","text":"Whether the music zone is enabled when loading the level. When disabled, no music will be played in the zone.
Accepted values:
TRUE
\u2014 Enable the music zone when loading the level FALSE
\u2014 The not enable the zone "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#priority","title":"priority
","text":"The priority of the music zone if two zones overlap. A higher number means a higher priority. 0
is the lowest possible priority.
Warning
Only relevant if two zCZoneMusic
zones overlap.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#ellipsoid","title":"ellipsoid
","text":"Determines the shape of the zone.
Accepted values:
TRUE
\u2014 The zone forms an ellipsoid within the bounding box. FALSE
\u2014 The zone exactly mirrors the bounding box. "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#reverblevel","title":"reverbLevel
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#volumelevel","title":"volumeLevel
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#loop","title":"loop
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#local_enabled","title":"local_enabled
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#dayentrancedone","title":"dayEntranceDone
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#nightentrancedone","title":"nightEntranceDone
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/","title":"oCZoneMusicDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/#oczonemusicdefault","title":"oCZoneMusicDefault","text":"Quick Infos
Class Name: oCZoneMusicDefault
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
Determines the default music to be played when the camera is outside any oCZoneMusic
zones. The volume-related options of the zone are ignored. There may only be one oCZoneMusicDefault
object in a world.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/","title":"zCVobSound","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#zcvobsound","title":"zCVobSound","text":"Quick Infos
Class Name: zCVobSound
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 12289
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Emits a sound defined by a script instance in a given radius. The sound playback can be activated by sending an OnTrigger
event to the VObject and sending an OnUntrigger
event disables the sound playback.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" soundIsRunning = FALSE soundAllowedToRun = FALSE zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" soundIsRunning = FALSE soundAllowedToRun = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndvolume","title":"sndVolume
","text":"The volume of the sound effect in percent (0-100).
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndmode","title":"sndMode
","text":"Determines how the sound effect is played.
Accepted values:
LOOPING
\u2014 The sound effect is repeated endlessly ONCE
\u2014 The sound plays once RANDOM
\u2014 The sound effect is repeated endlessly with a random delay between repetitions "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndranddelay","title":"sndRandDelay
","text":"The average delay between repetitions in seconds if sndMode
is RANDOM
.
Warning
Only relevant if sndMode
is RANDOM
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndranddelayvar","title":"sndRandDelayVar
","text":"The maximum deviation of the random delay between repetitions if sndMode
is RANDOM
. The resulting delay will be a value between sndRandDelay
\u00b1 sndRandDelayVar
.
Warning
Only relevant if sndMode
is RANDOM
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndstarton","title":"sndStartOn
","text":"Whether to start the sound when loading the world.
Accepted values:
TRUE
\u2014 Start the sound when the world is loaded FALSE
\u2014 Only start the sound in response to an OnTrigger
event "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndambient3d","title":"sndAmbient3D
","text":"Determines whether the sound is an omnidirectional ambient sound. It will change volume depending on the distance to this VObject, but it won't sound as if this VObject is emitting the effect.
Accepted values:
TRUE
\u2014 Emit an ambient sound effect FALSE
\u2014 Emit a directional sound effect "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndobstruction","title":"sndObstruction
","text":"Whether to dampen the sound when there is no direct path from the VObject to the listener.
Accepted values:
TRUE
\u2014 The sound is dampened by obstructions FALSE
\u2014 The sound is not dampened "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndconeangle","title":"sndConeAngle
","text":"When set to a value other than 0
, determines a cone in front of the VObject in which the sound can be heard. To listeners outside of that cone, the sound is not heard. Only values between 0
and 360
are valid.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndvoltype","title":"sndVolType
","text":"Determines the type of volume used to check whether the sound can be heard.
Accepted values:
SV_SPHERE
\u2014 The sound the be heard in a sphere around this VObject. SV_ELLIPSOID
\u2014 The sound can be heard within an ellipsoid defined by the VObject's bounding box. "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndradius","title":"sndRadius
","text":"The radius in which the sound can be heard.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndname","title":"sndName
","text":"The name of the script instance describing the sound.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#soundisrunning","title":"soundIsRunning
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#soundallowedtorun","title":"soundAllowedToRun
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/","title":"zCVobSoundDaytime","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#zcvobsounddaytime","title":"zCVobSoundDaytime","text":"Quick Infos
Class Name: zCVobSoundDaytime
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 12289
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Emits a sound defined by a script instance in a given radius during a given time during the day. Optionally, another sound can be defined which is played outside the defined time range (example: birds during the day and crickets at night).
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndstarttime","title":"sndStartTime
","text":"The time of day after which the sound can be heard (13.5
corresponds to 13:30
). Must be less than sndEndTime
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndendtime","title":"sndEndTime
","text":"The time of day after which the sound can no longer be heard (13.5
corresponds to 13:30
). Must be greater than sndStartTime
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndname2","title":"sndName2
","text":"The name of the script instance describing the sound to play outside the hours defined by sndStartTime
and sndendtime
. May be empty.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/","title":"zCZoneVobFarPlane","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#zczonevobfarplane","title":"zCZoneVobFarPlane","text":"Quick Infos
Class Name: zCZoneVobFarPlane
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the loading range of VObjects within its bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#vobfarplanez","title":"vobFarPlaneZ
","text":"The loading range of VObject within.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#innerrangeperc","title":"innerRangePerc
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/","title":"zCZoneVobFarPlaneDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/#zczonevobfarplanedefault","title":"zCZoneVobFarPlaneDefault","text":"Quick Infos
Class Name: zCZoneVobFarPlaneDefault
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the default loading range of VObjects in the entire world. There may only be one of these objects in each world. Its effect can be overridden using zCZoneVobFarPlane objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/","title":"zCZoneZFog","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#zczonezfog","title":"zCZoneZFog","text":"Quick Infos
Class Name: zCZoneZFog
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which causes fog to appear within its bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 fadeOutSky = FALSE overrideColor = FALSE zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 fadeOutSky = FALSE overrideColor = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fograngecenter","title":"fogRangeCenter
","text":"The maximum distance of visibility if the player is in the center of the fog object.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#innerrangeperc","title":"innerRangePerc
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fogcolor","title":"fogColor
","text":"The color of the fog.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fadeoutsky","title":"fadeOutSky
","text":"Whether to hide the sky when the player is inside the fog.
Accepted values:
TRUE
\u2014 Do not show the skybox when the player is inside the fog. FALSE
\u2014 Do show the skybox when the player is inside the fog. Warning
This property is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#overridecolor","title":"overrideColor
","text":"Unclear.
Warning
This property is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/","title":"zCZoneZFogDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/#zczonezfogdefault","title":"zCZoneZFogDefault","text":"Quick Infos
Class Name: zCZoneZFogDefault
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the default fog for the entire world. There may only be one of these objects in each world. Its effect can be overridden using zCZoneZFog objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault "}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Gothic Modding Community page","text":""},{"location":"#welcome-to-gothic-modding-community-page","title":"Welcome to Gothic Modding Community page","text":"This GitHub page is designed to contain community maintained set of articles, tutorials and documentation for everything Gothic.
Info
The content here is not meant to be taken as the holy word of modding. We are just modders sharing our experiences, knowledge and our favorite work flows.
Discord Server
If you have any modding related questions, or just want to talk join our discord server.
Discord
Contribution
Feel free to open a pull request with your article or propose changes. Here is detailed contribution guide.
How to Contibute
Gothic Archive
First two Gothic games use engine called ZenGin, developed by Piranha Bytes and Mad Scientists. If you want to know more about the history of the development, there is a heap of information on the Gothic Archive.
Gothic Archive
Repository
Check out our GitHub repository for the site's source code and updates.
GitHub
"},{"location":"notready/","title":"None","text":"Warning
Sorry, this page is not ready yet!
"},{"location":"preferences/","title":"Preferences","text":""},{"location":"preferences/#preferences","title":"Preferences","text":"This page allows to set various preferences for reading the docs:
"},{"location":"preferences/#color","title":"Color","text":"You can change the feel of the site with a color change.
Select accent color:
Select hue color:
Reset colors
"},{"location":"preferences/#font","title":"Font","text":"You can change the font to another preset.
Select font: Default OpenDyslexic
"},{"location":"preferences/#custom-css","title":"Custom CSS","text":"You can add custom stylesheets. Input CSS:
"},{"location":"contribute/","title":"How to contribute","text":""},{"location":"contribute/#how-to-contribute","title":"How to contribute","text":"The Gothic Modding Community is a community-driven project. We encourage people to contribute.
This site is built with a Static Site Generator MkDocs and the Material for MkDocs theme together with multiple other MkDocs plugins.
Prerequisites for contribution differ based on the scale and type of the contribution.
"},{"location":"contribute/#feedback","title":"Feedback","text":"Using English, you can either open an issue via GitHub or join us on Discord.
"},{"location":"contribute/#direct-contribution","title":"Direct contribution","text":"Direct contribution is made via creating a copy of this repository (a fork) and creating a pull request (PR) on GitHub with changes for approval.
Don't waste time
Please make sure that the content you are contributing does not already exist on the dev page. You can use the search tool to filter GMC for different keywords and contents.
How to edit the source files?
The source files for the articles are written using the Markdown .md
file format (Markdown cheatsheet). Other than that, this site also uses Python Markdown Extensions which add more syntax rules like indented admonitions.
"},{"location":"contribute/#minor-changes","title":"Minor changes","text":"Minor changes like fixing typos, grammatical errors or removing/adding words to paragraphs in a single file can be done quickly with the button in the upper right corner of each article. This will open up a GitHub editing interface which will create a fork with a patch branch after modifying the file and guide the user to open up the pull request.
Select the correct branch for the pull request
Make sure that the pull request is directed towards the dev
or a special pre-merge
branch and not the main
branch.
"},{"location":"contribute/#major-changes","title":"Major changes","text":"More elaborate changes like editing multiple files at once, adding new articles, images, other miscellaneous files or changing the configuration of the page are easier to make via external tools on your local PC. While most of these operations can be done with the GitHub interface, it is rather cumbersome, and it may be harder to spot issues during the process as changes are not immediately visible in the browser in their final form.
Some preparation is needed before working on the files as MkDocs requires an installation of Python on the system to run. GitHub works on top of git so an installation of git is also required. A basic familiarity with Terminal/Command Prompt/Powershell command line interfaces is helpful.
"},{"location":"contribute/#system-setup-video","title":"System setup (video)","text":"Firstly, you should install Python. You can follow this step-by-step tutorial for Windows or macOS on how to install Python.
This video is from 2017?!
The process of installing Python hasn't changed since that point. However, please install the latest version of Python 3.
To work remotely with GitHub, you can install the latest version of git on your system following this tutorial.
If you just plan on editing the content of the articles with Markdown, you can simply install the latest version of Visual Studio Code for GUI git management and Markdown preview or work with any other familiar text editor and omit the environment setup.
If you are planning to do some elaborate Python programming, you can follow this step-by-step tutorial for Windows or macOS on how to set up an environment with Visual Studio Code.
"},{"location":"contribute/#system-setup-text","title":"System setup (text)","text":"To prepare your system to run the project follow those instructions:
Install the latest version of Python . Make sure to select the \"Add Python to PATH\" option during the installation process.
Open up a Terminal/Command Prompt (cmd)/Powershell window.
Check that Python was properly installed with this command (might need a terminal restart):
python --version\n
Install the latest version of git following this tutorial.
Check that git was properly installed with this command (might need a terminal restart):
git --version\n
(optional) Install the latest version of Visual Studio Code for GUI git management and Markdown preview.
"},{"location":"contribute/#working-locally","title":"Working locally","text":"In order to work locally:
Create a fork on GitHub. On your local PC navigate to a directory where you want to clone your forked repository and open a Terminal window inside. Clone the forked repository, using this command:
git clone https://github.com/user-name/forked-repository-name.git <DIR-PATH>\n
Instead of https://github.com/user-name/forked-repository-name.git
use your own link which can be found after clicking on the green <> Code
button and selecting the HTTPS
tab.
Replace the <DIR-PATH>
with a path to a directory or .
if you're inside the directory you want the project files to be cloned into.
This will automatically create a remote origin
repository pointing to your own fork.
Add the remote upstream
repository using this command:
git remote add upstream https://github.com/Gothic-Modding-Community/gmc.git\n
(optional) Create a Virtual Environment and activate it.
If you work on multiple Python projects, it might be worthwhile to create a Virtual Environment for each project to have separate library directories with installed modules/plugins.
python -m venv venv\n
This will create a venv
directory inside the current Terminal directory. Please keep that name as it's added to the .gitignore
project file.
Depending on the system, use one of these commands to activate the virtual environment.
Linux / macOSsource venv/bin/activate\n
Windows Powershellvenv\\Scripts\\activate.ps1\n
Windows Command Prompt (cmd)venv\\Scripts\\activate.bat\n
After activation there will be a (venv)
indicator near the Terminal prompt.
Don't close the Terminal
The virtual environment must be activated each time a new Terminal window is opened.
Install MkDocs with plugins using this command:
pip install -r requirements.txt\n
This will install all dependencies.
Fetch the git history from upstream
using this command:
git fetch upstream\n
Checkout a new local branch based on the upstream
dev
branch:
git checkout -b name-of-branch --track upstream/dev\n
An appropriate name for a branch is either a feature name or short description of what it changes - for example 3ds-articles
, fix-typos-for-contribution
. They do not have to be elaborate, up-to 4 words suffices.
Start a server with MkDocs using this command:
mkdocs serve\n
Visit the local site with this url http://127.0.0.1:8000/gmc/
. Any time you make change to any file, the website will rebuild itself and your browser will auto-refresh.
The server may be closed using the Control-C
shortcut while in the terminal/console.
When you are satisfied with a part of work, add and commit the files using these commands:
git add .\ngit commit -m \"add 3 articles about ZenGin\"\n
An appropriate commit message should be a sentence describing the changes.
When you are finished with the work, push the branch to origin
using this command:
git push origin name-of-branch\n
Create the pull request to the appropriate branch.
After pushing your local branch to the remote origin
, there will be a link available in the Terminal window. Use it to create the pull request using the pushed branch.
Another contribution:
Before contributing again, always use this command:
git fetch upstream \n
to make sure that you have an up-to-date upstream
git history. Follow then from step 8. git status\n
This command allows to check, if there are any changes in the project compared to the upstream
repository.
"},{"location":"contribute/#build-preferences","title":"Build preferences","text":"While working with the project, it's possible to set various environmental variables to configure it to your own preferences:
GMC_DEV_LOCALE
- is a 2-character language identifier (ex. en
, pl
), it sets the development language of the site. This will enforce that language to be the default and only built language. Helps to decrease build time and allows to easily change the language without modyfying the config file. Because of changes in the mkdocs-static-i18n
plugin, this is the only way to temporarily change the default language GMC_BUILD_ALTERNATES
- True
or False
value, activates the site build to also include alternate languages apart of the default language. Default behaviour is to omit alternates to decrease build time. GMC_ENABLE_ON_PUBLISH
- True
or False
value, activates all of the final build procedures, like adding of the last modified date, minifying of the resources etc. Environmental variables can be set temporarily for the currently open Terminal window:
Linuxexport GMC_DEV_LOCALE=en export GMC_BUILD_ALTERNATES=False; mkdocs serve\n
Windows Powershell$env:GMC_DEV_LOCALE=\"en\"\n$env:GMC_BUILD_ALTERNATES=\"False\"\nmkdocs serve\n
Windows Command Prompt (cmd)set GMC_DEV_LOCALE=en\nset GMC_BUILD_ALTERNATES=False\nmkdocs serve\n
"},{"location":"contribute/#build-performance","title":"Build performance","text":"To speed up the build process during development make sure that only 1 language is built, and consider using the --dirtyreload
option:
mkdocs serve --dirtyreload\n
This will cause only changed .md
files to rebuild. However, if you make changes to a template in the overrides
directory, no changes will be visible after the rebuild, because template modification requires a full rebuild.
"},{"location":"contribute/#submit-a-file","title":"Submit a file","text":"If working with git or Markdown is not viable or possible for you, you can submit files in a Google Docs format on the GMC Discord server and we will format and upload it to the page.
Only New English Content
This option is limited to new content in English. We can't deal with translations in this manner. For translations send a translated .md
file via a feedback channel, if you don't want to work directly with git, nor add the file via the GitHub interface.
"},{"location":"contribute/#translations","title":"Translations","text":"To provide multilingual support, our site uses the MkDocs i18n plugin.
"},{"location":"contribute/#add-new-language-support","title":"Add new language support","text":"To support a new language it needs to be added:
Indentation is important
You must preserve the correct amount of indentation, aka spacing between entries.
In the mkdocs.yml
configuration, in this example we're adding the xx
language:
plugins:\n - i18n:\n # ...\n languages:\n en:\n name: en - English\n build: true\n xx:\n name: xx - Language Name\n build: true\n
In the overrides/main.html
file to add the announcement text for untranslated content:
{%\n set announcement = {\n \"en\": \"This page has not yet been translated into LANGUAGE, therefore it is displayed in English.\",\n \"xx\": \"yyy\",\n }\n%}\n{%\n set call_to_action = {\n \"en\": \"Support us and translate!\",\n \"xx\": \"yyy\",\n }\n%}\n
Visit the official theme site. Make sure that the theme translation is complete there. If it's not, just follow their contribution guide and come back here, there is no need to wait for the changes in the theme.
"},{"location":"contribute/#add-translated-pages","title":"Add translated pages","text":"Each .md
file in the docs
directory can have a translated version. To add a translation for a given language create a copy with an added language suffix. For example index.md
will become index.xx.md
for the xx
language based on the settings in the mkdocs.yml
file.
Each untranslated article has the button in the upper right corner next to the title. It allows to quickly add the translation via the GitHub interface without the need for local file configuration.
"},{"location":"genome/","title":"Genome engine","text":""},{"location":"genome/#genome-engine","title":"Genome engine","text":"Genome engine is new engine by Piranha Bytes created for the game Gothic 3 and later used for the Risen and ELEX series of games.
"},{"location":"genome/general_info/object_persistence/","title":"Object persistence","text":""},{"location":"genome/general_info/object_persistence/#object-persistence","title":"Object persistence","text":"Please note the following warning about Risen 2, 3 and ELEX 1 and 2
The following information only applies to Gothic 3 (2006) and Risen (2009). While newer Genome engine games share the same overall concepts, they have significant implementation differences that warrant their own section.
The engine is, due to the nature of the games themselves, required to store and load a vast amount of different types of data from the user's hard-drive. In order to streamline this parsing and/or serialization process, Genome implements an object persistence system using its own built-in runtime type information (RTTI) system.
Any class derived from bCObjectBase
may declare its own member properties in such a way that when the object is then written into a file using the bCAccessorPropertyObject
class, its associated properties will be automatically serialized into the stream by using special preprocessor macros. When the object is read back from the file, the class will be automatically initialized using the stored members.
Additionally, classes may overload the Read
and Write
(OnRead
and OnWrite
in Risen 1) virtual methods that allow the class to save additional data required during parsing such as paths to other necessary files.
As this system is quite flexible, it is used to store most of the game's data, from meshes, animations and textures to level and quest data. This is quite different from ZenGin, as its object persistence system is only used for worlds, saves, output units and parts of compiled meshes.
"},{"location":"genome/general_info/object_persistence/#file-format","title":"File format","text":""},{"location":"genome/general_info/object_persistence/#files","title":"Files","text":"struct bCIOStream\n{\n char data[];\n};\n
struct eCArchiveFile\n{\n char8_t magic[8]; // \"GENOMFLE\"\n uint16_t version; // 0001\n uint32_t offset;\n\n char data[];\n\n uint32_t magic; // DEADBEEF\n uint8_t version; // 01\n uint32_t count;\n for( Count )\n {\n uint16_t length;\n char8_t string[length]; // (ASCII)\n }\n};\n
"},{"location":"genome/general_info/object_persistence/#bcaccessorpropertyobject","title":"bCAccessorPropertyObject","text":"bCAccessorPropertyObject::Read \n{\n uint16_t version; // 0x0001\n bool hasPropertyObject;\n if (hasPropertyObject)\n {\n bCPropertyObjectSingleton::ReadObject\n {\n uint16_t version; // 0x0001\n bool isPersistable; // 0x01 (GETrue)\n bCString className;\n bCPropertyObjectFactory::ReadObject\n {\n uint16_t version; // 0x0001\n bool isRoot; // 0x00 (GEFalse)\n uint16_t classVersion;\n bTPropertyObject<%,%>::Read\n {\n bCPropertyObjectBase::Read\n {\n uint16_t version; // 0x00C9 (201)\n }\n uint32_t size;\n }\n bTPropertyObject<%,%>::ReadData\n {\n bCPropertyObjectBase::ReadData\n {\n uint16_t version; // 0x00C9 (201)\n uint32_t count;\n for (count)\n {\n bCString name;\n bCString type;\n uint16_t version; // 0x001E (30)\n uint32_t size;\n uint8_t value[size];\n }\n }\n %::Read\n {\n // ClassName::OnRead/OnWrite()\n // uint16_t ClassVersion; ...\n }\n }\n }\n }\n }\n}\n
"},{"location":"genome/general_info/object_persistence/#ecprocessibleelement","title":"eCProcessibleElement","text":"Gothic 3Risen eCProcessibleElement::Load\n{\n uint32_t magic; // 0xD0DEFADE\n bCAccessorPropertyObject::Read\n {\n // Look above for bCAccessorPropertyObject definition\n }\n}\n
eCProcessibleElement::Load\n{\n bCAccessorPropertyObject::Read\n {\n // Look above for bCAccessorPropertyObject definition\n }\n}\n
"},{"location":"genome/general_info/object_persistence/#implementation","title":"Implementation","text":""},{"location":"genome/general_info/object_persistence/#a-practical-example","title":"A practical example","text":"Let's propose that we have a class which is declared like so:
class gCMyClass : public bCObjectRefBase\n{\npublic:\n\n gCMyClass() {}\n virtual ~gCMyClass() {}\n\n virtual bEResult Write(bCOStream&); // OnWrite for Risen\n virtual bEResult Read(bCIStream&); // OnRead for Risen\n\nprivate:\n\n DECLARE_PROPERTY(myInt, int);\n\n int someData;\n\n};\n
The hypothetical class then implements these virtual functions:
bEResult gCMyClass::Write(bCOStream& file)\n{\n file << someData;\n return bEResult_Ok;\n}\n\nbEResult gCMyClass::Read(bCIStream& file)\n{\n file >> someData;\n return bEResult_Ok;\n}\n
We then initialize the class in the following way:
gCMyClass object;\nobject.myInt = 1;\nobject.someData = 1;\n
If we now serialized, or to use the engine's term \"archived\", this instance into an ASCII stream, the result would look like this:
\n
"},{"location":"genome/tools/","title":"Tools","text":""},{"location":"genome/tools/#tools","title":"Tools","text":"Piranha Bytes did not release a modkit for their Genome engine, but the modding community has released a wide range of tools to work with the game's files and the engine itself.
Info
This page is under construction, for now, only handful of links are present.
"},{"location":"genome/tools/#gothic-3-sdk","title":"Gothic 3 SDK","text":"Georgeto, inspired by NicoDE's Risen SDK, has created an SDK for Gothic 3. It can be used to manipulate the engine in the similar way Union is able to manipulate ZenGin. GitHub repository
"},{"location":"zengin/","title":"ZenGin","text":""},{"location":"zengin/#zengin","title":"ZenGin","text":"The game engine ZenGin is used by Gothic 1 and 2. This section contains the documentation of the various aspects of ZenGin modding.
Script Reference
ZenGin uses its own scripting language called Daedalus. Check its functions, classes and extenders.
Scripts
Vob Classes
Virtual objects are objects which appear in the game world.
zCVob
Animations Section
Create new animations and put them into the game.
Animations
Union SDK
Learn how to create plugins with Union SDK, a community-made software development kit for ZenGin.
Getting Started
"},{"location":"zengin/music/","title":"Music","text":""},{"location":"zengin/music/#music","title":"Music","text":"Zengin uses DirectMusic for playing in-game soundtrack. To edit Gothic music files you need the Direct Music Producer, a program released by Microsoft and provided with older DirectX SDK.
Warning
Music files can't be packed in the .vdf
or .mod
archives, all music files must be located in /_work/Data/Music
directory.
"},{"location":"zengin/music/#file-formats","title":"File formats","text":"The music directory contains these file types:
.dls
- Downloadable Sound format file. This is the base for all other files. Contains:
Collections of virtual musical instruments. Wave files instruments use. .sty
- Style file. Contains:
Bands - settings for virtual instruments from .dls
. Patterns - fragments of tracks, that can be later merged, looped and superimposed on each other .sgt
- File with properly connected patterns - the final track
"},{"location":"zengin/music/#alternative-music-system","title":"Alternative Music System","text":"The zBassMusic plugin replaces Zengin's default music library with the much newer BASS library. This allows, among other things, to play music in such formats as .mp3
or .ogg
, and to pack songs into .vdf
and .mod
archives.
"},{"location":"zengin/video/","title":"Video","text":""},{"location":"zengin/video/#video","title":"Video","text":"To get a video cutscene, intro or outro into the game, the video needs to be in a proper format - BINK video format .bik
.
"},{"location":"zengin/video/#editing-the-video","title":"Editing the video","text":"The video you recorded and want to use has to be edited. My go-to editor for this is kdenlive. It works very well, it is free and open source, and it supports BINK video as an input, which is great if you want to include subtitles in the video.
My version of kdenlive does not know how to export video straight to .bik
so I just export my video to .mp4
and then convert it with RAD Video Tools.
"},{"location":"zengin/video/#rad-video-tools","title":"RAD Video Tools","text":"RAD Video Tools is a tool for converting other video formats to BINK .bik
that Gothic can use.
Warning
Gothic 1 bink implementation has some problems as you have to set the audio compression to 104 and above in RAD tools to get video to work in Gothic 1.
NicoDE's comment:
Add 100 to the audio compression level when encoding videos, e.g. 104 for level 4 with old sound format (should be mentioned in the RAD Video Tools documentation) for G1 without updated Miles libraries.
Note
Newest Union (1.0m at the time of writing) has a new patch for BINK video playback. The issue with sound should be fixed.
"},{"location":"zengin/anims/","title":"Animation","text":""},{"location":"zengin/anims/#animation","title":"Animation","text":""},{"location":"zengin/anims/#animations-in-zengin","title":"Animations in ZenGin","text":"Animations are (apart from maybe advanced programming work using Ikarus or Union) one of the most advanced modding techniques, since you not only must understand the way they work, but also know how to write the animation script and understand the whole scheme selection system, naming convention and of course know how to animate (that is my biggest problem :D). To get a new animation into ZenGin (the Gothic engine) is not difficult per se, I would describe it as tedious.
Luckily, there are tools to help us to achieve our goal - get a new animation to be used by the engine, and in effect, to be used and seen in the game.
To describe the whole process, I constructed this small tutorial, to help other people to get animations working and to spare them many hours of searching the excellent forum posts, that describe parts of the process. __
Excluding advanced programming work with Ikarus or Union, animations are arguably the most advanced modding discipline of ZenGin engine. Its difficulty stems for the fact that you not only have to understand the general concept, but also learn how to write the animation scripts and understand the whole scheme selection system, including naming conventions and, most important for last - actually know how to animate. Adding new animations into ZenGin is more tedious than actually difficult.
There are tool to help with this endeavor - to get a new animation implemented in the engine, and seeing its effects in game. Following tutorial has been constructed to help others to get their animations working without having to scour old forum posts for hours.
"},{"location":"zengin/anims/#prerequisites---tools--materials","title":"Prerequisites - Tools & Materials","text":" Gothic Mod Development Kit (MDK) Gothic 1 MDK - link Gothic 2 MDK - link Blender Kerrax's Import Export plugin - follow the installation instructions to install the plugin, make sure to set up the texture paths too Tool for decompiling animations GothicSourcer, or use phoenix or write your own using ZenLib "},{"location":"zengin/anims/#the-workflow","title":"The workflow","text":"This is the basic step-by-step workflow on how to get the animation into the game.
Load the actor (character or object) into your 3D software Create your animation Export the animation as an .asc
file Write the MDS file Run the game to compile your animations Test your animations in-game using a Daedalus script or a console command Sounds simple enough, except there is a lot missing. Even though the steps start with loading the actor into blender, understanding the system of animations to get high quality assets into your mod is more important.
"},{"location":"zengin/anims/#animation-types","title":"Animation \"types\"","text":"There are two main types of animations - skeletal
and morphmesh
animations. Character body animations are skeletal, and we animate the skeleton and the entire model (skin) moves around it. Morph mesh animation is, on the other hand, used for facial animations such as eating, blinking or talking and for animated meshes like wave water ferns or fish in Khorinis' harbor.
This guide focuses on skeletal animations. There are few different ones, all of which will have their own demonstration in the future. Categories are:
Standalone animation - waving, bowing, eating MOBSI animations - bed, alchemy table, anvil Item animations - sweeping the floor with a broomstick, using the horn, playing the lute Mandatory animations - running, walking, sneaking Combined/interpolated animations - picking stuff up, aiming with a bow/crossbow All of these animations are defined in an MDS file which will be talked about in the next sections.
"},{"location":"zengin/anims/events/","title":"None","text":"Acknowledgment
This tutorial was possible thanks to Kerrax, VAM and their excelent articles (MDS, EventTags) and Avallach from theModders who provided valuable insight.
"},{"location":"zengin/anims/events/#animation-event-block-overview","title":"Animation event block overview","text":"We often need to perform some other actions together with our animation, such as playing a sound effect, inserting item into NPC's hand or changing an item instance into a different one, like turning a raw steel into hot raw steel. These actions often need to be done at very specific moment during the animation playback, therefore they are defined using events(#aniamtion-events) in the event block which follows right after the animation definition. The event block is started and closed by curly brackets.
Example:
ani (\"s_RunL\" 1 \"s_RunL\" 0.0 0.1 M. \"Hum_RunLoop_M01.asc\" F 12 31) // animation\n{ // event block start\n\n *eventSFXGrnd (12 \"Run\") // animation event\n *eventSFXGrnd (24 \"Run\") // animation event\n ...\n *eventSFXGrnd (30 \"Run\") // animation event\n} // event block end\n
Warning
Each animation can define a maximum of 16 events. Should you need more, split the animation into parts and use next_ani
to chain them together.
"},{"location":"zengin/anims/events/#animation-events","title":"Animation events","text":"Animation events are commands telling engine to do something. Event *eventSFXGrnd(12 \"Run\")
will command the engine to play sound Run
at the very moment (12th frame) the character lands food on the ground. So with that in mind here is the general syntax as well as each animation event in the game.
General Syntax:
*EVENTNAME (FRAME KEYWORD \"INSTANCE\" [OPTIONAL] [A:VALUE] [B:VALUE])\n
FRAME
- all events specify on what frame int the animation source file .ASC
should this event happen
KEYWORD
- some events expect very specific keywords.
\"INSTANCE\"
- this indicates parameter is expected to be inside quotes, usually it;s slot/bone or item/sound instance name from the scrips
[OPTIONAL]
- this is an example of the optional parameter. Optional parameters will be indicated by brackets []
, if you don't specify them, the event will use the default value defined by the engine.
A:VALUE
- some events that have more than one optional parameter use a prefix to know which was specified
NODE_NAME
- will indicate any NODE
should work, be it bones (BIP01
...) or ZS_
slots (ZS_RIGHTHAND
)
SLOT
- this will indicate most likely only ZS_
slots will work.
Warning
Events should follow in ascending order by the frame they appear on. i. e. *eventTag(1 ...)
must come before *eventTag(2 ...)
Event Description eventCamTremor camera shake eventMMStartAni start morph-mesh eventPFX create particle effect eventPFXStop destroy particle effect eventSwapMesh exchange item meshes between two slots eventSFX create sound effect eventSFXGRND create sound effect on the ground eventTag generic event, does action specified in parameters Defined in engine but never used ? eventPFXGRND create particle effect on the ground eventSetMesh ? modelTag same as eventTag, but applies to morphmesh?"},{"location":"zengin/anims/events/#eventcamtremor","title":"eventCamTremor","text":"Earthquake effect (camera shake)
Example:
*eventCamTremor (12 1000 500 2 8 )\n
Syntax:
*eventCamTremor (FRAME RANGE DURATION MIN_AMPLIFIER MAX_AMPLIFIER)\n
eventCamTremor
- is a keyword, for camera shake event
Let's describe all the parameters
FRAME
- animation frame at which this event starts
RANGE
- range from which the effect will be 'felt' defined in in-game centimeters (1000 is 10 meters in-game)
DURATION
- duration of the effect in milliseconds
MIN_AMPLIFIER
- minimum amount of shaking in in-game centimeters
MAX_AMPLIFIER
- the maximum amount of shaking.
"},{"location":"zengin/anims/events/#eventmmstartani","title":"eventMMStartAni","text":"Start the animation of the morph-mesh that is attached to the specified node. Mostly used to start NPC facial animations or to animate bows/crossbows shooting.
Example:
*eventMMStartAni (14 \"T_HURT\")\n*eventMMStartAni (6 \"S_SHOOT\" \"ZS_RIGHTHAND\")\n*eventMMStartAni (6 \"S_BOOK_NEXT_PAGE\" \"ZS_RIGHTHAND\" I:0.5 H:5)\n
Syntax:
*eventMMStartAni (FRAME \"ANI_NAME\" [\"NODE_NAME\"] [I:INTENSITY] [H:HOLD_TIME])\n
FRAME
- animation frame at which animation should start
ANI_NAME
- name of the morph-mesh animation (specified in .MMS) file
NODE_NAME
- node in the hierarchy, to which morph mesh is attached. If not specified, a default value of BIP01 HEAD
will be used.
I:INTENSITY
- float value to specify blending of morph animation with the current one ?
H:HOLD_TIME
- time in seconds, how long will the animation \"stay\"
Both INTENSITY
and HOLD_TIME
can be specified in the MMS script. All gothic morph meshes specify those values in .MMS, therefore behavior when both specified in eventMMStartAni and .MMS file is unknown/untested
"},{"location":"zengin/anims/events/#eventpfx","title":"eventPfx","text":"Start particle effect at the specified bone.
Example:
*eventPFX (12 \"ZMODELLANDDUST\" \"Bip01\" )\n*eventPFX (2 1 \"DEMON_ATTACK\" \"BIP01 R HAND\" ATTACH)\n
Syntax:
*eventPFX (FRAME [PFX_HANDLE] \"PFX_NAME\" \"NODE_NAME\" [ATTACH])\n
FRAME
- animation frame at which particle effect starts
PFX_NAME
- name of the PFX instance
PFX_HANDLE
- an optional integer value. Specifying this creates a 'handle' and allows stop the PFX later using eventPFXStop
NODE_NAME
- node in the hierarchy. particle effect will be spawned at the node's position. If not specified, a default value of BIP01
will be used.
ATTACH
- keyword, including this keyword, will make particle effect follow the node specified, otherwise, it will stay where it spawned.
Tip
ATTACH
is used to create demons burning hand during the attack, while without this keyword dust particles are made to stay at the position where NPC landed after falling.
"},{"location":"zengin/anims/events/#eventpfxstop","title":"eventPFXStop","text":"Stops particle effect previously started by eventPfx
Example:
*eventPFX (2 1 \"DEMON_ATTACK\" \"BIP01 R HAND\" ATTACH) // starts pfx with handle 1\n...\n*eventPFXStop (70 1) // stops pfx started above\n
Syntax:
*eventPFXStop (FRAME PFX_HANDLE)\n
FRAME
- animation frame at which particle effect should disappear
PFX_HANDLE
- an integer value. Handle of the particle effect, that should be destroyed. Particle effect must be spawned using the same handle by eventPfx first
"},{"location":"zengin/anims/events/#eventswapmesh","title":"eventSwapMesh","text":"Move mesh from source NODE
to target node. Item should be present in the node already. Only mesh of the Items is moved, engine internally still keeps a reference to items in the original slot? Never used in game?
Example:
*eventSwapMesh (5 \"ZS_CROSSBOW\" \"ZS_LEFTARM\")\n
Syntax:
*eventSWAPMESH (FRAME \"SOURCE_NODE_NAME\" \"TARGET_NODE_NAME\")\n
FRAME
- animation frame at which transport of the mesh should happen
SOURCE_NODE_NAME
- source node containing the item.
TARGET_NODE_NAME
- target node that the item should be moved to.
Note
In some rare occasions duplicates item
"},{"location":"zengin/anims/events/#eventsfx","title":"eventSfx","text":"Play sound effect. It can be either SFX
instance from scripts, or .WAV
file.
Example:
*eventSFX (0 \"Drown\")\n*eventSFX (8 \"WHOOSH\" EMPTY_SLOT)\n*eventSFX (8 \"BAB_SIGH\" R:5000 EMPTY_SLOT) \n
Syntax:
*eventPFX (FRAME \"SFX_NAME\" [R:RANGE] [EMPTY_SLOT])\n
FRAME
- animation frame at which particle effect starts
SFX_NAME
- name of the SFX instance or .WAV
file
R:RANGE
- an optional integer value. The range from which the effect will be 'heard' defined in in-game centimeters (1000 is 10 meters in-game)
[EMPTY_SLOT]
- optional keyword. By default audio effects use a single audio channel (slot) per Model. That means every eventSFX
request will cancel any currently playing effect. If EMPTY_SLOT
is specified, audio will be played on the next available (empty) audio slot and other sounds will not be interrupted.
Note
A lot of original game animations contain EMTPY_SLOT
instead of EMPTY_SLOT
which was probably unintended. Gothic therefore acts as no keyword was provided, which causes a lot of sound interruptions. Therefore be mindful of spelling when copying original MDS scripts
"},{"location":"zengin/anims/events/#eventsfxgrnd","title":"eventSfxGrnd","text":"the same as eventSfx with only one difference, the sound effect name is appended with the current material name.
Example:
*eventSFXGrnd (12 \"Run\")\n
Syntax:
*eventSFXGrnd (FRAME \"SFX_NAME\" [R:RANGE] [EMPTY_SLOT])\n
Depending on the material of the texture, the character is standing on, the game will add one of the following suffixes:
Spacer Material Suffix Gothic 1 Gothic 2a UNDEF
_Undef \u2714\ufe0f \u2714\ufe0f EARTH
_Earth \u2714\ufe0f \u2714\ufe0f SAND
_Sand \u2714\ufe0f \u2714\ufe0f METAL
_Metal \u2714\ufe0f \u2714\ufe0f WATER
_Water \u2714\ufe0f \u2714\ufe0f WOOD
_Wood \u2714\ufe0f \u2714\ufe0f SNOW
_Snow \u274c \u2714\ufe0f STONE
_Stone \u2714\ufe0f \u2714\ufe0f default _Stone \u2714\ufe0f \u2714\ufe0f NPC running on grass texture, with material set to EARTH in world editor, will play sound Run_Earth
by using *eventSFXGrnd (12 \"Run\")
in run animation. _Earth
suffix is determined and added by the engine.
"},{"location":"zengin/anims/events/#eventtag","title":"eventTag","text":"This is a generic type of event that does different actions based on the first parameter after the frame parameter. It was probably later in development to extend MDS functionality without the need to expand parser itself. All parameters except FRAME
are passed inside quotes Further parameters are specific for every EVENT_TAG_TYPE
.
Waning
eventTag contrary to other events is validated only at runtime. If parameters are wrong, it won't work or might crash the game
Syntax:
*eventTag (FRAME \"EVENT_TAG_TYPE\" \"PARAMETER_1\" \"PARAMETER_2\" ... \"PARAMETER_N\")\n
FRAME
- Frame at which the event will execute. This parameter is always first and the same for all eventTags
EVENT_TAG_TYPE
- a type of event = action that should happen.
Here is a list of event tag types:
EVENT TAG TYPE Description DEF_CREATE_ITEM Creates item into slot DEF_INSERT_ITEM Inserts item to slot from inventory DEF_REMOVE_ITEM Removes item from slot to inventory DEF_DESTROY_ITEM Destroys item in slot DEF_PLACE_ITEM ~~Places item from slot into mob slot~~ Destroys item in slot DEF_EXCHANGE_ITEM Removes item in slot and replaces with new item DEF_FIGHTMODE Sets npc into weapon stance DEF_PLACE_MUNITION Inserts munition into slot DEF_REMOVE_MUNITION Remove munition back to inventory DEF_DRAWSOUND Plays weapon drawing sound based on weapon material DEF_UNDRAWSOUND Plays weapon sheating sound based on weapon material DEF_SWAPMESH Moves items visual to different slot visually DEF_DRAWTORCH Inserts torch DEF_INV_TORCH Moves torch to different slot temporarily DEF_DROP_TORCH Drops torch from slot to world DEF_HIT_LIMB Defines node which deals damage DEF_DIR Defines attack direction DEF_DAM_MULTIPLIER Defines damage mutliplier DEF_PAR_FRAME Defines frame range for blocking DEF_OPT_FRAME Defines damage frames DEF_HIT_END Defines last frame to continue combo DEF_WINDOW Defines frame for combo continuation"},{"location":"zengin/anims/events/#def_create_item","title":"DEF_CREATE_ITEM","text":"Creates a new item instance and inserts it into the specified slot. Item is not inserted permanently but only for the duration of interaction.
Example:
*eventTag (4 \"DEF_CREATE_ITEM\" \"ZS_RIGHTHAND\" \"ItMw_1H_Mace_L_04\")\n
Syntax:
*eventTag (FRAME \"DEF_CREATE_ITEM\" \"SLOT\" \"ITEM_INSTANCE\")\n
SLOT
- a name of the ZS_
slot, write in UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_insert_item","title":"DEF_INSERT_ITEM","text":"Insert the interaction item into the specified slot.
during mob interaction, inserted item instance is of instance taken from UseWithItem mob property. during item interaction (i.e. drink potion) item that started the SceneName will be inserted. In the example below: (1)
inserts ItMiSwordrawhot
that is defined in spacer into ZS_LEFTHAND
, then (2)
spawns ItMw_1H_Mace_L_04
(hammer) into ZS_RIGHTHAND
for anvil interaction.
Example:
ani (\"t_BSANVIL_S0_2_S1\" 1 \"s_BSANVIL_S1\" 0.0 0.0 M. \"Hum_BSAnvil_Jue00.asc\" F 4 9)\n{\n *eventTag (4 \"DEF_INSERT_ITEM\" \"ZS_LEFTHAND\") // (1)\n *eventTag (4 \"DEF_CREATE_ITEM\" \"ZS_RIGHTHAND\" \"ItMw_1H_Mace_L_04\") // (2)\n}\n
Syntax:
*eventTag (FRAME \"DEF_INSERT_ITEM\" \"SLOT\")\n
SLOT
- a name of the ZS_
slot, use UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
The well-known Gothic bug:
If player gets hit while drinking a potion, the effect of the potion is applied, but the potion remains in the inventory - the reason for the bug is that the potion item is inserted into hand using DEF_INSERT_ITEM
and would be removed from the world at the end of the drinking animation, while the potion's effect (a script function that increases stats) is applied at the very beginning of the animation. When the player is hit, the drinking animation is interrupted, and the engine does not remove the item from the world.
"},{"location":"zengin/anims/events/#def_remove_item","title":"DEF_REMOVE_ITEM","text":"Remove an item inserted into a slot via DEF_INSERT_ITEM
from the slot back into the inventory.
Example:
*eventTag (0 \"DEF_REMOVE_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_REMOVE_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_destroy_item","title":"DEF_DESTROY_ITEM","text":"Destroys an item inserted into a slot via DEF_INSERT_ITEM
. The item is removed from the world.
Example:
*eventTag (0 \"DEF_DESTROY_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_DESTROY_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_place_item","title":"DEF_PLACE_ITEM","text":"Remove the item inserted via eventTag DEF_INSERT_ITEM
from the slot and the world. In terms of its action, eventTag DEF_PLACE_ITEM
is a synonym for DEF_DESTROY_ITEM
. Possibly fixed by SystemPack. See intended use.
Example:
*eventTag (0 \"DEF_PLACE_ITEM\")\n
Syntax:
*eventTag (FRAME \"DEF_PLACE_ITEM\")\n
Warning
This event tag most likely works only during Mob/Item interaction
Intended use Presumably, the eventTag DEF_PLACE_ITEM
was intended to have different behavior: If an NPC interacts with a MOB that has a ZS_SLOT
node, then move the item inserted via DEF_INSERT_ITEM
from the NPC node into the ZS_SLOT
node on the MOB. An example would be orc priest hearts in the Temple of the Sleeper, Gothic 1.
// Sleeper Portal\nani (\"t_SPORTAL_Stand_2_S0\" 1 \"s_SPORTAL_S0\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 0 19)\nani (\"s_SPORTAL_S0\" 1 \"s_SPORTAL_S0\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 20 20)\nani (\"t_SPORTAL_S0_2_Stand\" 1 \"\" 0.0 0.2 M. \"Hum_SleeperPortal_M01.asc\" R 0 19)\nani (\"t_SPORTAL_S0_2_S1\" 1 \"s_SPORTAL_S1\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 21 90 FPS:10)\n{\n *eventTag (60 \"DEF_INSERT_ITEM\" \"ZS_RIGHTHAND\") // (1)\n *eventTag (90 \"DEF_PLACE_ITEM\") // (2)\n}\nani (\"s_SPORTAL_S1\" 1 \"s_SPORTAL_S1\" 0.0 0.0 M. \"Hum_SleeperPortal_M01.asc\" F 91 91)\nani (\"t_SPORTAL_S1_2_Stand\" 1 \"\" 0.0 0.2 M. \"Hum_SleeperPortal_M01.asc\" F 90 100)\n
During animation on 60th frame,(1)
inserts orc priest sword from the inventory, and (2)
on 90th frame, presumably, should have left the sword inserted into the heart sticking out. There is ZS_SLOT
present to indicate the location of the sword after insertion into the heart.
In reality, (2)
simply removes the sword from the world like DEF_DESTROY_ITEM
. This was most likely an unrealized idea. In G2, eventTag DEF_PLACE_ITEM
is not used.
"},{"location":"zengin/anims/events/#def_exchange_item","title":"DEF_EXCHANGE_ITEM","text":"Replace an item in a slot with another item. Item present in the slot is removed from the slot and the world, new item specified in parameters is created and inserted in the same slot.
Example:
*eventTag (37 \"DEF_EXCHANGE_ITEM\" \"ZS_LEFTHAND\" \"ItMiSwordrawhot\")\n
Syntax:
*eventTag (FRAME \"DEF_EXCHANGE_ITEM\" \"SLOT\" \"ITEM_INSTANCE\")\n
SLOT
- a name of the ZS_
slot, use UPPERCASE
ITEM_INSTANCE
- item instance from the scripts
Warning
This event tag most likely works only during Mob/Item interaction
"},{"location":"zengin/anims/events/#def_fightmode","title":"DEF_FIGHTMODE","text":"Set fight mode for the model. Used in transition animations to weapon stances like t_1h_2_1hRun
.
Example:
*eventTag (5 \"DEF_FIGHTMODE\" \"FIST\")\n
Syntax:
*eventTag (FRAME \"DEF_FIGHTMODE\" \"FIGHT_MODE\")\n
FIGHT_MODE
- fight modes are defined in the engine and can be one of the following:
\"\"
- remove weapon \"FIST\"
- fists \"1H\"
or \"1HS\"
- one-handed weapon \"2H\"
or \"2HS\"
- two-handed weapon \"BOW\"
- bow \"CBOW\"
- crossbow \"MAG\"
- magic Example: Parameter 1H
sets fight mode for the actor (in the engine), but also exchanges sword from ZS_SWORD
slot to the ZS_RIGHTHAND
"},{"location":"zengin/anims/events/#def_place_munition","title":"DEF_PLACE_MUNITION","text":"Place ammunition, from inventory such as an arrow into the specified slot. Used in reloading animations after a bow/crossbow shot.
Example:
*eventTag (9 \"DEF_PLACE_MUNITION\" \"ZS_RIGHTHAND\")\n
Syntax:
*eventTag (FRAME \"DEF_PLACE_MUNITION\" \"SLOT\")\n
SLOT
- slot where the ammunition is created. There are only two valid slot names: \"ZS_LEFTHAND\"
and \"ZS_RIGHTHAND\"
.
Ammunition always corresponds to the equipped ranged weapon instance and its munition
field in the C_ITEM
instance
instance ItRw_Sld_Bow(C_Item)\n{\n name = \"\u041b\u0443\u043a\";\n mainflag = ITEM_KAT_FF;\n flags = ITEM_BOW;\n material = MAT_WOOD;\n value = Value_SldBogen;\n damageTotal = Damage_SldBogen;\n damagetype = DAM_POINT;\n munition = ItRw_Arrow;\n cond_atr[2] = ATR_DEXTERITY;\n cond_value[2] = Condition_SldBogen;\n visual = \"ItRw_Sld_Bow.mms\";\n description = name;\n text[2] = NAME_Damage;\n count[2] = damageTotal;\n text[3] = NAME_Dex_needed;\n count[3] = cond_value[2];\n text[5] = NAME_Value;\n count[5] = value;\n};\n
"},{"location":"zengin/anims/events/#def_remove_munition","title":"DEF_REMOVE_MUNITION","text":"Remove ammunition previously placed by DEF_PLACE_MUNITION event
Example:
*eventTag (19 \"DEF_REMOVE_MUNITION\")\n
Syntax:
*eventTag (FRAME \"DEF_REMOVE_MUNITION\")\n
"},{"location":"zengin/anims/events/#def_drawsound","title":"DEF_DRAWSOUND","text":"Play weapon drawing sound. Determined by drawn weapon material
field in the C_ITEM
instance
\u201cDrawSound_WO.wav\u201d
- for MAT_WOOD; \"DrawSound_ME.wav\"
- for MAT_METAL. Example:
*eventTag (19 \"DEF_DRAWSOUND\")\n
Syntax:
*eventTag (FRAME \"DEF_DRAWSOUND\")\n
"},{"location":"zengin/anims/events/#def_undrawsound","title":"DEF_UNDRAWSOUND","text":"Play weapon sheathing sound. Determined by drawn weapon material
field in the C_ITEM
instance
\"UndrawSound_WO.wav\u201d
- for MAT_WOOD; \"UndrawSound_ME.wav\"
- for MAT_METAL. Example:
*eventTag (19 \"DEF_UNDRAWSOUND\")\n
Syntax:
*eventTag (FRAME \"DEF_UNDRAWSOUND\")\n
"},{"location":"zengin/anims/events/#def_swapmesh","title":"DEF_SWAPMESH","text":"Swap items in the specified slots.
Example:
*eventTag (5 \"DEF_SWAPMESH\" \"ZS_CROSSBOW\" \"ZS_LEFTHAND\")\n
Syntax:
*eventTag (FRAME \"DEF_SWAPMESH\" \"SLOT1\" \"SLOT2\")\n
SLOT1
- name of the slot with item to be exchanged.
SLOT2
- name of the slot with item to be exchanged.
Warning
In case SLOT1
or SLOT2
is equal to \"ZS_LEFTHAND\"
or \"ZS_RIGHTHAND\"
, the engine will attempt to put the model into fight mode similar to DEF_FIGHTMODE event. This can lead to game freezing.
Tip
This event is similar to the *eventSwapMesh. The main difference is *eventSwapMesh will swap only visuals (meshes) of the items, while eventTag DEF_SWAPMESH will swap items and their slot references. After a game reload, meshes would reset their positions if swapped using *eventSwapMesh. Additionally *eventSwapMesh does not try to set the model into fight mode.
"},{"location":"zengin/anims/events/#def_drawtorch","title":"DEF_DRAWTORCH","text":"Does nothing? never used.
Example:
*eventTag (5 \"DEF_DRAWTORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_DRAWTORCH\")\n
"},{"location":"zengin/anims/events/#def_inv_torch","title":"DEF_INV_TORCH","text":"Temporarily return torch into inventory, for the duration of mob/item interaction. Does nothing if a torch is not present in ZS_LEFTHAND
. Used before interacting with mobs like bed, or before performing eating animations that require a left hand.
Example:
*eventTag (5 \"DEF_INV_TORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_INV_TORCH\")\n
"},{"location":"zengin/anims/events/#def_drop_torch","title":"DEF_DROP_TORCH","text":"Drop the torch onto the ground if present in ZS_LEFTHAND
.
Example:
*eventTag (5 \"DEF_DROP_TORCH\")\n
Syntax:
*eventTag (FRAME \"DEF_DROP_TORCH\")\n
"},{"location":"zengin/anims/events/#def_hit_limb","title":"DEF_HIT_LIMB","text":"Set which node is dealing damage to others. This node is then used in calculations for collisions. Up to four slots can be specified.
Example:
// humans - fist attacks\n*eventTag (0 \"DEF_HIT_LIMB\" \"BIP01 R HAND\")\n// humans - sword attacks\n*eventTag (0 \"DEF_HIT_LIMB\" \"ZS_RIGHTHAND\")\n// animals \neventTag (0 \"DEF_HIT_LIMB\" \"BIP01 HEAD\")\n
Syntax:
*eventTag (FRAME \"DEF_HIT_LIMB\" \"SLOT1\" \"SLOT2\" \"SLOT3\" \"SLOT4\")\n
"},{"location":"zengin/anims/events/#def_dir","title":"DEF_DIR","text":"Set the direction of the attack. Enemy block animation is determined by this information. Not used.
Example:
*eventTag (0 \"DEF_DIR\" \"O\")\n*eventTag (0 \"DEF_DIR\" \"L\")\n*eventTag (0 \"DEF_DIR\" \"OUOL\") // combo attack - top, under, \n
Syntax:
*eventTag (FRAME \"DEF_DIR\" \"DIRECTIONS\")\n
DIRECTIONS
- can be up to 10 characters, each character defines one attack direction during combo attack, default is O
- capital letter O
, not zero 0
. Possible values are
If the enemy is trying to block an attack with a defined direction it will choose a matching animation adding a direction suffix like t_1hParade_U
for opponent's attack direction U
Note
Sadly this feature was unused in Gothic 1. All attacks use O
direction and only defined animations for blocking are for said t_1hParade_O
But can be easily restored with a few new animations and MDS file edits. In Gothic 2, blocking animation uses zero 0
instead of O
which might indicate the feature no longer works.
"},{"location":"zengin/anims/events/#def_dam_multiplier","title":"DEF_DAM_MULTIPLIER","text":"Set damage multiplier. For the attack animation. The damage will be multiplied by a provided number regardless of whether the attack is a critical attack or not.
Example:
*eventTag (0 \"DEF_DAM_MULTIPLIER\" \"0.2\")\n*eventTag (0 \"DEF_DAM_MULTIPLIER\" \"2.0\")\n
Syntax:
*eventTag (FRAME \"DEF_DAM_MULTIPLIER\" \"MULTIPLIER\")\n
MULTIPLIER
- float value inside quotes
"},{"location":"zengin/anims/events/#def_par_frame","title":"DEF_PAR_FRAME","text":"Set frame range during which damage is blocked. If not provided whole animation is blocking damage.
Example:
*eventTag (0 \"DEF_PAR_FRAME\" \"1 8\")\n
Syntax:
*eventTag (FRAME \"DEF_PAR_FRAME\" \"START_FRAME_END_FRAME\")\n
START_FRAME_END_FRAME
- Two integer numbers inside quotes. if \"0 0\"
is provided, the animation will be blocking it's whole duration
"},{"location":"zengin/anims/events/#def_opt_frame","title":"DEF_OPT_FRAME","text":"Set frames during which damage collisions should be evaluated. Damage is checked for collision with \"hit limb\". This event usually comes in pair with eventTags DEF_WINDOW and DEF_HIT_END
Example:
*eventTag (0 \"DEF_OPT_FRAME\" \"6\") // on hit attack, hit on 6th frame\n*eventTag (0 \"DEF_OPT_FRAME\" \"6 30\") // 2 attack combo, hit at 6th and 30th frame\n
Syntax:
*eventTag (FRAME \"DEF_OPT_FRAME\" \"HIT_FRAME1 HIT_FRAME2 ... HIT_FRAME10\")\n
HIT_FRAME1 HIT_FRAME2 ... HIT_FRAME10
- specify 1 and up to 10 integers separated by space inside quotes. Each number represents frame at which damage should be done. Number of provided hit frames determines number of combos (max 10 possible).
"},{"location":"zengin/anims/events/#def_hit_end","title":"DEF_HIT_END","text":"Set frames at which the combo is \u201ccut off\u201d if you do not press the \u201cup\u201d key (G1) or the left mouse button (G2) during the attack. Gothic has bug that in this case we will hear all the sound effects following this frame, and the animation ends with the character\u2019s characteristic twitching. The number of frames specified in this entry must match the number of frames of the eventTag DEF_OPT_FRAME.
Example:
*eventTag (0 \"DEF_HIT_END\" \"32\") \n*eventTag (0 \"DEF_HIT_END\" \"27 48 75\") \n
Syntax:
*eventTag (FRAME \"DEF_HIT_END\" \"HIT_END1 HIT_END2 ... HIT_END10\")\n
HIT_END1 HIT_END2 ... HIT_END10
- specify 1 and up to 10 integers separated by space inside quotes. After this frame combo cannot be continued and model will continue animation until the current DEF_WINDOW -
1`. Which is usually animation returning to idle stance
"},{"location":"zengin/anims/events/#def_window","title":"DEF_WINDOW","text":"Set a \u201cwindow\u201d in the animation - an interval of frames during which you need to press the \u201cup\u201d (G1) or the left mouse button (G2) to continue the combo strike.
Example:
*eventTag (0 \"DEF_WINDOW\" \"9 19\") // one combo with window from 9-19 (can be chained)\n*eventTag (0 \"DEF_WINDOW\" \"10 23 32 41 58 70\") // 3 combos with windows 10-23 then 32-41, 58-70\n
Syntax:
*eventTag (FRAME \"DEF_WINDOW\" \"HIT_1_WINDOW_START HIT_1_WINDOW_END HIT_2_WINDOW_START HIT_2_WINDOW_END ...\")\n
HIT_1_WINDOW_START HIT_1_WINDOW_END HIT_2_WINDOW_START HIT_2_WINDOW_END
- specify 1 and up to 20? integers separated by space inside quotes. A window consists of a start and end frame, therefore for each DEF_OPT_FRAME, you must provide 2 numbers.
HIT_WINDOW_START
- First value of the pair defines frame from which attack can continue. HIT_WINDOW_END
- Second value is a little confusing. It defines START of the next attack animation. Ability to continue combo stops at DEF_HIT_END frames. Usually there are few frames of animation, where characters returns to idle position. HIT_WINDOW_END
should be one frame after characters return to idle stance, which should also be first frame of the next attack "},{"location":"zengin/anims/events/#attack-eventtags-explained","title":"Attack eventTags explained","text":"This is original attack combo from Gothic 1
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n *eventTag (0 \"DEF_HIT_LIMB\" \"ZS_RIGHTHAND\")\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 36 73 107\") \n *eventTag (0 \"DEF_HIT_END\" \"31 63 95 113\")\n *eventTag (0 \"DEF_WINDOW\" \"10 33 42 65 78 97 110 113\")\n *eventSFX (4 \"Whoosh\" EMPTY_SLOT )\n *eventSFX (72 \"BACK\" EMPTY_SLOT )\n}\n
I will edit it slightly to make it more readable. Let's focus on the DEF_OPT_FRAME, DEF_HIT_END,
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n ...\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 36 73 107 \") \n *eventTag (0 \"DEF_HIT_END\" \" 31 63 95 113\")\n *eventTag (0 \"DEF_WINDOW\" \" 10 33 42 65 78 97 110 113\")\n ...\n}\n
Let's focus only on the first combo.
ani (\"s_1hAttack\" 1 \"s_1hAttack\" 0.0 0.1 M. \"Hum_1hAttackComboT3_M05.asc\" F 1 114)\n{\n ...\n *eventTag (0 \"DEF_OPT_FRAME\" \"4 ...\") \n *eventTag (0 \"DEF_HIT_END\" \" 31 ...\")\n *eventTag (0 \"DEF_WINDOW\" \" 10 33 ...\")\n ...\n}\n
Frames Animation Description 1 animation start 1..4 swing of the sword 4 sword is in the front of the model DEF_OPT_FRAME
- test damage collisions at this frame 4..10 end of the sword swing 10 model stands ready to start next swing DEF_WINDOW
- user can press key to advance combo from this frame. 10..31 slight idle 'shake' if player continues combo, animation playback will jump to the frame 33 (DEF_WINDOW
second pair), from the animation perspective, next attack starts from pose similar to frame 10. If perfect inputs would be provided, animation would continue perfectly. 31 DEF_HIT_END
- ends user input. 31..32 model returns to the idle position 32 idle position, standing with sword in hand animation will end here, if combo not continued (DEF_WINDOW
second pair - 1) 33 first frame of the next attack (similar to frame 10) DEF_WINDOW
second pair, start of next attack"},{"location":"zengin/anims/events/#eventpfxgrnd","title":"eventPfxGrnd","text":"Not used anywhere in the original game. Could possibly spawn particle effect like eventPfx but with an added suffix similar to how eventSfxGrnd works. Needs to be investigated.
Syntax:
*eventPFXGRND (FRAME)\n
"},{"location":"zengin/anims/events/#eventsetmesh","title":"eventSetMesh","text":"Unknown
Syntax:
*eventSETMESH (FRAME \"NODE_NAME\")\n
"},{"location":"zengin/anims/events/#modeltag","title":"modelTag","text":"Should work similarly to eventTag, but can be defined inside aniEnum block and applies to all animations of the Model.
Syntax:
*modelTag (FRAME \"EVENT_TAG_TYPE\" \"PARAMETER1\" \"PARAMETER2\" \"PARAMETER3\" \"PARAMETER4\" ... )\n
"},{"location":"zengin/anims/mds/","title":"MDS - model animation script","text":""},{"location":"zengin/anims/mds/#mds---model-animation-script","title":"MDS - model animation script","text":"Tip
The MDS syntax is very simple and scripts can be edited in any text editor. It is, however, easier to work in an editor with a proper syntax highlighting. Daedalus Language Server's dev branch already merged the MDS grammar for syntax highlighting, we can expect it in the next release.
Model animation script is a file describing what skeleton should be used, what body meshes work with this set of animations and how should the animations be named, how fast they run, what animation is supposed to start after the current one is finished and much more. These files are located in Gothic\\_work\\DATA\\Anims\\
directory.
Whilst the code seems long and terrifying, it is in fact rather simple, and this guide will try to explain it whole.
Don't forget to use the search
If you search this file for t_Yes
, you will get an example of the first type of animation - \"standalone\"
To play the animation in game you use this console command play ani t_yes
.
"},{"location":"zengin/anims/mds/#syntax-and-keywords","title":"Syntax and keywords","text":"Let us get a quick look at the naming convention to get a basic idea what is going on before we start.
The first letter indicates a type of animation (transition - t_
- or state - s_
). Then depending on the animation type we have:
Transition animation
t_Run_2_Sneak\n
Transition animation from the run animation to the sneak animation. t_BSANVIL_Stand_2_S0\n
Transition animation for the blacksmith's anvil from standing to state 0. State animation
s_Run\n
State animation for the looping animation. s_BSANVIL_S0\n
State animation for the blacksmith's anvil and its first state."},{"location":"zengin/anims/mds/#ani","title":"ani","text":"This is the main command you will be using while defining new animations.
Example:
ani (\"t_Yes\" 2 \"\" 0.1 0.1 M. \"Hum_Yes_M01.asc\" F 1 44)\n
Syntax: ani (ANI_NAME LAYER NEXT_ANI BLEND_IN BLEND_OUT FLAGS ASC_NAME ANI_DIR START_FRAME END_FRAME)\n
ani
- is a keyword, we are defining new animation Let's describe all the parameters
ANI_NAME
- animation name, we use it in Daedalus as animation identifier
There is a naming convention, that is recommended and sometimes required to be used.
prefix t_
- transition animations prefix s_
- state animations - they usually run in a loop prefix c_
- animations used for animation combining/interpolation LAYER
- layer number for multi-layer animations
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
If we set it to 0.5, it takes 0.5 seconds for this animation to take full effect. At 0.0 s the previous animation has full effect on the bones of the skeleton, at 0.1 s it is influenced by 20% by this animation and at 0.5s it is completely influenced by this animation and the previous one has no effect.
BLEND_OUT
- time in seconds describing animation blending at the end
FLAGS
- flags, that describe animation behavior
M - specifies a movement animation, the animation of the model translates into a changed position in the game world R - the same as M but for rotation E - this flag makes this animation run only, if the animation in the same layer are finished, this is used in the movement animations. The animation s_walk
(walking loop animation) runs, when the player is walking,when he stops the transition animation to standing state is played t_walk_2_stand
. This animation uses the E flag to wait for the walk cycle animation to finish, to smoothly transition into the standing state. F - the engine ignores height coordinate - doesn't keep the model \"glued\" to the ground (falling/flying animation) I - specifies idle animation - breathing, standing with a drawn weapon and moving the weapon ASC_NAME
- name of the source file exported from Blender
ANI_DIR
- direction of the animation
START_FRAME
- on what frame from the source file the animation starts
END_FRAME
- on what frame from the source file the animation ends
"},{"location":"zengin/anims/mds/#anialias","title":"aniAlias","text":"Generally considered as one of the most useful commands, aniAlias
is used to create an alias (hard link for UNIX users) for an already defined animation.
Example:
aniAlias (\"t_Sneak_2_Run\" 1 \"s_Run\" 0.0 0.1 M. \"t_Run_2_Sneak\" R)\n
Syntax: aniAlias (ANI_NAME LAYER NEXT_ANI BLEND_IN BLEND_OUT FLAGS ALIAS_NAME ANI_DIR)\n
ANI_NAME
- name of the new animation
LAYER
- layer the animation is on
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
BLEND_OUT
- time in seconds describing animation blending at the end
FLAGS
- flags, that describe animation behavior
ALIAS_NAME
- name of the animation we want to use as a source for the alias
ANI_DIR
- direction of the animation
If we look for the animation in the example we can see that there is a related one just one line above
ani (\"t_Run_2_Sneak\" 1 \"s_Sneak\" 0.1 0.0 M. \"Hum_Sneak_M01.asc\" F 0 10)\naniAlias (\"t_Sneak_2_Run\" 1 \"s_Run\" 0.0 0.1 M. \"t_Run_2_Sneak\" R)\n
In this example we are defining t_Sneak_2_Run
animation and we are specifying that the animation after this one is finished will be s_Run
and that it is being made by reversing animation t_Run_2_Sneak
by specifying the R
flag."},{"location":"zengin/anims/mds/#aniblend","title":"aniBlend","text":"AniBlend is used to define animations that are a result of blending of two animations. This animation is not animated by hand, but it is dynamically generated by the engine during run-time.
Example
aniBlend (\"t_RunR_2_Run\" \"s_Run\" 0.2 0.2)\n
Syntax: aniBlend (ANI_NAME NEXT_ANI BLEND_IN BLEND_OUT)\n
ANI_NAME
- name of the new animation
NEXT_ANI
- name of the next animations
BLEND_IN
- time in seconds describing animation blending at the start
BLEND_OUT
- time in seconds describing animation blending at the end
"},{"location":"zengin/anims/mds/#anisync","title":"aniSync","text":"Not used in the game.
"},{"location":"zengin/anims/mds/#anibatch","title":"aniBatch","text":"Not used in the game.
"},{"location":"zengin/anims/mds/#animation-state-machine","title":"Animation state machine","text":"More complex animations such as MOBSI animations form a state machine - an animation set.
MDS script for the big chestModel (\"CHESTBIG_OCCRATELARGE\")\n{\n meshAndTree (\"CHESTBIG_OCCRATELARGE.asc\")\n\n aniEnum\n {\n// Closed chest\n ani (\"s_S0\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 20 20)\n// Opening the chest \n ani (\"t_S0_2_S1\" 1 \"s_S1\" 0.0 0.0 M. \"CHESTBIG_USE.ASC\" F 50 79)\n {\n *eventSFX (50 \"chest_try\")\n *eventSFX (55 \"chest_open\")\n }\n// Opened chest\n ani (\"s_S1\" 1 \"s_S1\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 80 80)\n// Closing the chest\n ani (\"t_S1_2_S0\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" R 50 79)\n {\n *eventSFX (78 \"chest_close\")\n }\n// Pick lock broken\n ani (\"t_S0_Try\" 1 \"s_S0\" 0.0 0.0 M. \"CHESTBIG_USE.asc\" F 96 124)\n {\n *eventSFX (100 \"chest_try\")\n *eventSFX (115 \"Hammer\")\n }\n }\n}\n
stateDiagram-v2\n s_S0 : Closed chest\n t_S0_2_S1 : Opening the chest\n s_S1 : Opened chest\n t_S1_2_S0 : Closing the chest\n t_S0_Try : Pick lock broken\n [*] --> s_S0\n s_S0 --> s_S0\n\n s_S0 --> t_S0_2_S1\n t_S0_2_S1 --> s_S1\n s_S1 --> s_S1\n\n s_S1 --> t_S1_2_S0\n t_S1_2_S0 --> s_S0\n\n s_S0 --> t_S0_Try\n t_S0_Try --> s_S0
"},{"location":"zengin/anims/tutorials/standalone_animation/","title":"Standalone animation","text":""},{"location":"zengin/anims/tutorials/standalone_animation/#standalone-animation","title":"Standalone animation","text":"Acknowledgment
This tutorial would not be possible without the ZenGin documentation available in the mod-kit. Further credits also go to Mark56 who helped me understand animations in the first place, Fawkes and his request for me to do some animations for his excellent mod - Replay Mod, and last but not least Flosha from the Phoenix team who was the one for whom I offered to write this tutorial to help with the development of the Phoenix project.
Let us start with the easiest animation - a very simple gesturing animation.
Info
You can find some of the videos that are mentioned in the text below in this play-list.
Firstly we have to have the animation source files ready. Best way to decompile them is using Gothic Sourcer. In GothicSourcer you choose Tools > Decompiler models > Dynamic (MDS or MSB) and choose an MDS file of your choice - Humans.mds
in our case and then click the decompile button.
"},{"location":"zengin/anims/tutorials/standalone_animation/#animating","title":"Animating","text":"Open Blender, File > Import > Kerrax ASCII model (.asc), navigate to the folder with your decompiled animation files and select HUM_BODY_NAKED0.ASC
. This file contains the skeleton and skin model for human NPCs.
What bone hierarchy is this model using?
If you open the .mds
file, you can see a command meshAndTree
that specifies what model contains the skeleton. And there lies our answer:
Model (\"HuS\")\n{\n meshAndTree (\"Hum_Body_Naked0.ASC\" DONT_USE_MESH)\n
A windows pops up and you can read some interesting information about the model you are about to import. We are interested in the fact that Completely replace current scene is ticked, we want to use Armature modifier, and we also want to Try to connect bones and Use sample meshes from folder. You should provide a path to a directory with the sample meshes - these are meshes for items, that usually go into slot bones. Lastly, the space transformation scale should be set to 0.01. This is because ZenGin works with centimeter units and one unit in Blender is a meter.
Click import and wait for the magic to happen.
This video shows a freshly imported model with all default meshes.
Note
If we now want to play (or edit) existing animation, we can now load it on top of this. Just as before File > Import > Kerrax ASCII model (.asc) and select different animation file (or armor file), for example Hum_SmokeHerb_Layer_M01.asc
for an animation file.
Gothic characters are modular and you can change their heads on the fly, even during gameplay as seen in this amazing video from my dear friend and colleague Fawkes - Head changing. Let's add a head so that we can see how the whole body will behave while we are animating. File > Import > Kerrax ASCII model (.asc), navigate to your head model. You will have to decompile it like we did with the body itself. We will import HUM_HEAD_PONY.ASC
. Please make sure to select the target bone for importing Bip01 Head, this will attach the head to the proper bone, just like the engine does it.
Now we have everything ready to start animating. The video shows the DopeSheet a nice way to edit keyframes.
DopeSheet
Blender's dope sheet can be used to copy entire sets of keyframes. It is useful if we want to create a looping animation.
We can import an animation into Blender as a base.
Tip
If you don't know the name of the animation, just go into the game and make your character perform the animation you want. While in MARVIN mode, you can press G
and the animation information together with other info will be displayed right on the screen
In this video we can see that the idle standing animation is s_run
. We want to make an animation that is going to start from this idle animation, so we will import it into blender. We find it by looking into the .mds
file, look for s_run
name and get the name of the file.
ani (\"s_Run\" 1 \"s_Run\" 0.1 0.1 MI \"Hum_RunAmbient_M01.asc\" F 1 50) \n
As we can see, we have to import the Hum_RunAmbient_M01.asc
file. Next goes the first trick. Since we want our animation to end exactly, as it started - ether because we want the hero to continue his standing animation, or we want to make a looping animation, we somehow have to copy the pose. We use the DopeSheet screen, to delete all keyframes and then copy the keyframe set from keyframe number 0 and drag it somewhere to the end of the timeline.
Once the animation is done, we have to export it into an asc
format again, File > Export > Kerrax ASCII model (.asc) and then save it to _work\\data\\Anims\\asc\\
so the engine can see it and convert it. There are many options here that we will explore later, but we have tick Export animation and pick bones that we want to export - this is useful for animations that are played on different layers (dialogue gestures, scratching head, scratching a shoulder,...).
"},{"location":"zengin/anims/tutorials/standalone_animation/#animation-script","title":"Animation script","text":"Now that we have exported the animation, we now have to define it in Humans.mds
.
Open the file, scroll to the end and define a new animation.
Attention
All ani
code has to be between the curly brackets, this means you have to insert it before the last two closing curly brackets } }
.
Example:
ani (\"t_backpain\" 1 \"\" 0.0 0.0 M. \"Hum_back.ASC\" F 0 121) \n
Save the Humans.mds
file and try it in game. Nothing happens! The reason is that the mds
has been already compiled, and we have to recompile it. The easiest is to go to Anims\\_compiled
and delete HUMANS.MSB
. Run the game and try to play the animation again (play ani t_backpain
in MARVIN console) and now everything should work.
Amazing, now you have your first animation in the game. And you can use it to do some fun stuff, like in dialogues using the AI_PlayAni
function.
"},{"location":"zengin/anims/tutorials/standalone_animation/#example-dialogue","title":"Example dialogue","text":"instance DIA_Xardas_Back (C_INFO)\n{\n npc = NONE_100_Xardas;\n nr = 11;\n condition = DIA_Xardas_Back_Condition;\n information = DIA_Xardas_Back_Info;\n permanent = TRUE;\n description = \"What's wrong?\";\n};\n\nfunc int DIA_Xardas_Back_Condition () {\n return TRUE;\n};\n\nfunc void DIA_Xardas_Back_Info () {\n AI_Output (self, hero, \"DIA_Xardas_MOB_14_00\"); // My back hurts so much.\n\n // This is our animation!!!!!\n AI_PlayAni(self, \"T_BACKPAIN\"); \n AI_Output (self, hero, \"DIA_Xardas_MOB_14_01\"); // How do YOU feel?\n\n AI_Output (hero, self, \"DIA_Xardas_MOB_14_02\"); // My back is fine.\n AI_StopProcessInfos(self);\n};\n
"},{"location":"zengin/general_info/directory_structure/","title":"ZenGin directory structure","text":""},{"location":"zengin/general_info/directory_structure/#zengin-directory-structure","title":"ZenGin directory structure","text":"Modding is all about changing the game files. To achieve that, we have to know the directory (folder) structure of a Gothic game.
\u251c\u2500\u2500 Data\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 $Templates$\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 modvdf\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 Plugins\n\u251c\u2500\u2500 Miles\n\u251c\u2500\u2500 Saves\n\u251c\u2500\u2500 System\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 Autorun\n\u2514\u2500\u2500 _work\n \u2514\u2500\u2500 DATA\n \u251c\u2500\u2500 Anims\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 _Compiled\n \u251c\u2500\u2500 Meshes\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 _Compiled\n \u251c\u2500\u2500 Music\n \u251c\u2500\u2500 Presets\n \u251c\u2500\u2500 Scripts\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 _compiled\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 content\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 CUTSCENE\n \u251c\u2500\u2500 Sound\n \u251c\u2500\u2500 Textures\n \u251c\u2500\u2500 Video\n \u2514\u2500\u2500 Worlds\n
"},{"location":"zengin/general_info/directory_structure/#data","title":"Data
","text":"Data directory contains .vdf
volumes of the game. These contain anims.vdf
- animations, speech.vdf
- dubbing, worlds.vdf
- world ZEN files.
"},{"location":"zengin/general_info/directory_structure/#saves","title":"Saves
","text":"Contains saved games.
"},{"location":"zengin/general_info/directory_structure/#system","title":"System
","text":"The system directory contains the game executable, GothicStarter.exe
, GothicStarter_mod.exe
, configuration .ini
files, mod .ini
files and mod icons and description .rtf
files.
system/Autorun
is a Union specific directory, it serves as a default search directory for Daedalus injection scripts with zParserExtender and Union plugins.
"},{"location":"zengin/general_info/directory_structure/#_workdata","title":"_work/DATA
","text":"This is where the magic happens:
Anims
- contains animations and animated models. _compiled
- contains compiled animations. Meshes
- contains meshes source and compiled files. _compiled
- contains compiled meshes. Music
- contains music files. Presets
- contains basic presets. Scripts
_compiled
- contains compiled scripts - .dat
files. Content
- contains scripts that make up the content of the game. System
- contains scripts that make up the menu. Sound
- contains sound effects .wav
or .ogg
format (Union only). Video
- contains videos in .bik
format. "},{"location":"zengin/general_info/object_persistence/","title":"Object persistence","text":""},{"location":"zengin/general_info/object_persistence/#object-persistence","title":"Object persistence","text":"In order to simplify the process of loading and saving data of various types to and from the user's hard-drive, ZenGin implements a simple object persistence system using the zCArchiver
class and its derivatives that allow the individual engine classes to implement a routine specifying which data should be saved or loaded from disk and in which manner.
An object that is derived from the zCObject
class may overload the Archive
and Unarchive
virtual methods. The class may then call on an interface provided by the zCArchiver
class within these methods which allows it to directly read from or write to a stream using several modes. Those are ASCII and BinSafe by default. There are, however, more options, as is explained below.
"},{"location":"zengin/general_info/object_persistence/#archive-format","title":"Archive format","text":"In order to better understand how this process works, it would be best to look at an example of a .ZEN file containing an instance of an oCWorld
object.
"},{"location":"zengin/general_info/object_persistence/#header","title":"Header","text":"When you open up a ZenGin archive, you will see the following at the start of the file:
ZenGin Archive\nver 1\nzCArchiverGeneric\nASCII\nsaveGame 0\ndate 7.1.2001 23:9:19\nuser roeske\nEND\nobjects 2594 \nEND\n
Let's look at each of these properties and what they mean:
ZenGin Archive
This simply specifies that the following data is an zCArchiver
archive.
ver 1
Version specification. Can be either 0
or 1
. Both Gothic 1 and 2 are already on version 1, although version 0 archives can also be occasionally found.
zCArchiverGeneric
Specifies which derived zCArchiver
class should be used to read this archive. Accepted values are zCArchiverGeneric
for ASCII and Binary archives, and zCArchiverBinSafe
for BinSafe archives. More info below. This property might not be present in older archives.
ASCII
This is the most important part of the header as it specifies in which format should the data be stored. There are 4 different modes:
ASCII - The simplest one. It stores data in human-readable ASCII notation (not unlike JSON for example). This is usually used when saving data during development and/or testing, while the final version of said data will most likely be stored as BIN_SAFE. ASCII_PROPS - Same as ASCII except with more additional data that the developer can specify for visual clarity. In practice, it is not used anywhere and mostly serves only to prettify debug info (try typing ZWORLD VOBPROPS
in the console and look in zSpy ;) ). BINARY - Binary representation of the class instance, which mostly copies the data 1:1 into/from the stream. In practice, this format is only used to store savefiles (.SAV). BIN_SAFE - BinSafe, short for Binary Safe, is an extended version of Binary which stores type information along with the data itself. This is meant to make error checking for invalid data easier. There are other changes which are explained below. Most, if not all world files (.ZEN), are stored in this format. saveGame 0
Specifies if this archive is a savefile. This property might not be present in older archives.
date 7.1.2001 23:9:19
The date at which this archive was created.
user roeske
The user which created the archive. This property might not be present in older archives.
END
Tells the parses that this is the end of the header.
We may additionally find a property called csum
in version 0 archives which stores the checksum of the whole archive. This property is, however, unused and equals 00000000
by default.
In order to correctly read the archive's header across varying engine versions, one should not count on the properties always being in the same order or even being there at all.
If the archive utilizes zCArchiverGeneric
then this header will also be followed by a short section specifying the number of object instances in this archive. This value will be used to initialize the objectList, which is an array of pointers where the addresses of loaded objects will be stored for later referencing. This property would be directly part of the main header in older versions.
objects 2594 END \n
If the archive is created using zCArchiverBinSafe
, this data will be stored in the following binary structure:
struct BinSafeArchiveHeader \n{ \n uint32_t version; // Always equals 2 uint32_t objectCount; // Serves the same function as \"objects n\" uint32_t chunkPos; // Offset to chunk hash table};\n}; \n
"},{"location":"zengin/general_info/object_persistence/#contents","title":"Contents","text":"Looking further into the archive, we see what appears to be a nested structure.
[% oCWorld:zCWorld 64513 0]\n [VobTree % 0 0]\n childs0=int:1\n [% zCVobLevelCompo:zCVob 12289 1]\n pack=int:0\n presetName=string:\n bbox3DWS=rawFloat:-71919.9609 -13091.8232 -59900 108999.992 20014.0352 67399.9922 \n trafoOSToWSRot=raw:0000803f0000000000000000000000000000803f0000000000000000000000000000803f\n trafoOSToWSPos=vec3:0 0 0\n vobName=string:LEVEL-VOB\n visual=string:SURFACE.3DS\n showVisual=bool:0\n visualCamAlign=enum:0\n cdStatic=bool:1\n cdDyn=bool:0\n staticVob=bool:0\n dynShadow=enum:0\n [visual zCMesh 0 2]\n []\n [ai % 0 0]\n []\n []\n ...\n
We primarily differentiate between chunks and properties within ZenGin archives:
"},{"location":"zengin/general_info/object_persistence/#chunks","title":"Chunks","text":"A chunk is a structure that groups properties together. For most of the time, a chunk represents a class instance. This is, however, not always true as classes may arbitrarily create chunks as is needed. For example, the sample above contains a chunk called VobTree
, which does not represent a class instance, but only serves to make the reading of the archive easier.
While in ASCII mode, the start of a chunk is represented using square brackets.
[% oCWorld:zCWorld 64513 0]
There are 4 pieces of data separated by spaces inside the start of each chunk, which are:
Object name - The name of the chunk to use while reading. If the chunk has no name, then it will be simply equal to %
. Class name - The name of the class which this chunk represents. Class names are stored with their full inheritance hierarchy (e.g. oCMobLadder:oCMobInter:oCMOB:zCVob
). In case the chunk is not an object, but an arbitrary chunk, then this field will be equal to %
(%
can also mean that this chunk is a nullptr). In some cases you may encounter the symbol \u00a7
instead. This means that the object already exists and that the parser should look for it in the objectList using the object index. Using this mechanism, a single instance can be referenced multiple times without worrying about duplicity. Class version - Used to ensure that the data being read is compatible with the current game/engine version, so that there are no mismatches in the data pattern. This value is different for every class and varies between game versions. Object index - An index into the objectList under which this object will be stored. If the class name is equal to \u00a7
, then this value will be used to retrieve an existing instance from the objectList. If this is a Binary archive, the same data will be stored in the following binary structure:
struct BinaryObjectHeader\n{\n uint32_t objectSize; // Size of the whole object in bytes\n uint16_t classVersion;\n uint32_t objectIndex;\n char objectName[]; // Null-terminated string\n char className[]; // Null-terminated string\n};\n
Oddly enough, if the archive is BinSafe, then the data will be encoded the same way as in ASCII mode, except that it will be stored as a type-checked property.
struct BinSafeObjectHeader\n{\n uint32_t type; // 0x1 = TYPE_STRING\n uint16_t length; // Length of the text\n char text[]; // [% oCWorld:zCWorld 64513 0]\n};\n
In ASCII mode []
represents the end of the current chunk.
"},{"location":"zengin/general_info/object_persistence/#properties","title":"Properties","text":"We find properties inside the chunks which are key-value pairs that classes use to store the actual data. Each property stores its name, type and value. In ASCII mode the format for this isname=type:value
.
For example:
visual=string:SURFACE.3DS
By default, zCArchiver
allows to store properties of the following types:
Int - A regular 32-bit integer. In ASCII mode, int gets stored as name=int:1
, while in Binary mode, it's just the raw value stored as 4 bytes.
Byte - A 8-bit integer. ASCII mode doesn't differentiate between Int and Byte, so this will be stored as name=int:1
regardless. Binary mode stores only the single byte.
Word - A 16-bit integer. ASCII mode doesn't differentiate between Int and Word, so this will be stored as name=int:1
regardless. Binary mode stores only the 2 bytes.
Float - A standard IEEE 754 32-bit floating point number. In ASCII mode the format is name=float:1.0
, while in Binary mode the float gets stored raw as 4 bytes.
Bool - Stores a single-byte boolean value. In ASCII mode its name=bool:1
and in Binary mode it's a single byte.
String - An ASCII encoded string. While in ASCII mode, strings are stored as name=string:value
. In Binary mode, strings are NULL terminated.
Vec3 - A three component vector, mainly used to store positional data. The ASCII mode format is name=vec3:1.0 1.0 1.0
. In Binary mode the three components of the vector are stored in series, which equals to a total size of 12 bytes.
Color - A 32-bit color value stored as BGRA. In ASCII mode the color is stored as name=color:255 255 255 255
while in Binary mode it's just 4 raw bytes.
Raw - Raw binary data. In order to maintain readability, in ASCII mode this gets stored as a hex encoded string such as name=raw:63D15B07
. In Binary mode, only the data itself is stored, without any other info. Be aware that due to this you must know the size of the data beforehand.
RawFloat - An array of floats, mainly used to store bounding boxes. In ASCII mode, the floats are stored as name=rawFloat:1.0 1.0 1.0 1.0 1.0 1.0
. In Binary mode the floats are stored in series as raw bytes. Same as with Raw
, you must know the size of the array beforehand.
Enum - An enum value. In ASCII mode, it gets stored as name=enum:1
. In Binary mode, it behaves the same as Int
.
As you might have noticed, binary mode doesn't perform any kind of checks on if it's reading the right property or even data of the correct type. This is why BinSafe mode exists, as it stores the property type in along with the data itself.
enum TYPE\n{\n TYPE_STRING = 0x1,\n TYPE_INTEGER = 0x2,\n TYPE_FLOAT = 0x3,\n TYPE_BYTE = 0x4,\n TYPE_WORD = 0x5,\n TYPE_BOOL = 0x6,\n TYPE_VEC3 = 0x7,\n TYPE_COLOR = 0x8,\n TYPE_RAW = 0x9,\n TYPE_RAWFLOAT = 0x10,\n TYPE_ENUM = 0x11\n TYPE_HASH = 0x12,\n};\n\nstruct BinSafeProperty\n{\n TYPE type;\n union\n {\n struct\n {\n uint16_t stringLength;\n char stringValue[];\n }\n uint32_t integerOrHashOrEnumValue;\n float floatValue;\n uint8_t byteOrBoolValue;\n zVEC3 vec3Value;\n zCOLOR colorValue;\n struct\n {\n uint16_t rawLength;\n char rawValue[];\n }\n struct\n {\n uint16_t rawFloatLength;\n float rawFloatValue[];\n } \n };\n};\n
Looking at the enumeration of types, you might notice that BinSafe mode has an additional property type called Hash. BinSafe archives include a hash table which is stored in the following manner:
struct BinSafeHashTable\n{\n uint32_t chunkCount;\n for (chunkCount)\n {\n uint16_t stringLength;\n uint16_t linearValue;\n uint32_t hashValue;\n char text[stringLength];\n }\n};\n
Instead of storing the raw value, properties may save a hash instead, which is then used to look up the corresponding value from the hash table.
"},{"location":"zengin/general_info/object_persistence/#implementation","title":"Implementation","text":"As mentioned in the opening paragraph, classes may use the described functionality by overloading the Archive
and Unarchive
virtual methods, which pass an instance of zCArchiver
by reference. When the class instance is then serialized and/or parsed, these methods are called and perform the desired serialization/parsing work.
The class uses methods provided by the zCArchiver
instance within these routines. These methods return/accept a value of a specific type (e.g. ReadInt/WriteInt), while they do the actual reading/writing work behind the scenes based on the current mode (ASCII/Binary/BinSafe). The programmer writing the class then does not care whether the final archive will be saved as ASCII, Binary or BinSafe, as they only use the zCArchiver
Read* and Write* methods.
"},{"location":"zengin/general_info/object_persistence/#a-practical-example","title":"A practical example","text":"Let's propose that we have a class which is declared like so:
class zCMyClass : public zCObject\n{\npublic:\n\n zCMyClass() {}\n virtual ~zCMyClass() {}\n\n virtual void Archive(zCArchiver&);\n virtual void Unarchive(zCArchiver&);\n\n int myInt;\n zCMyClass* myObject;\n zCMyClass* secondPointerToMyObject;\n\n};\n
The hypothetical class then implements these virtual functions:
void zCMyClass::Archive(zCArchiver& archiver)\n{\n archiver.WriteInt(\"myInt\", myInt);\n\n archiver.WriteObject(\"myObject\", myObject);\n\n archiver.WriteChunkStart(\"myChunk\", 0);\n archiver.WriteObject(\"secondPointerToMyObject\", secondPointerToMyObject);\n archiver.WriteChunkEnd();\n}\n\nvoid zCMyClass::Unarchive(zCArchiver& archiver)\n{\n archiver.ReadInt(\"myInt\", myInt);\n\n myObject = dynamic_cast<zCMyClass*>(archiver.ReadObject(\"myObject\"));\n\n archiver.ReadChunkStart(\"myChunk\");\n secondPointerToMyObject = dynamic_cast<zCMyClass*>(archiver.ReadObject(\"secondPointerToMyObject\"));\n archiver.ReadChunkEnd();\n}\n
We then initialize the class in the following way:
zCMyClass object;\n\nobject.myInt = 12121212;\n\nobject.myObject = new zCMyClass();\nobject.myObject->myInt = 34343434;\n\nobject.secondPointerToMyObject = object.myObject;\n
If we now serialized, or to use the engine's term \"archived\", this instance into an ASCII archive, the result would look like this:
ZenGin Archive\nver 1\nzCArchiverGeneric\nASCII\nsaveGame 0\ndate 3.7.2022 0:0:0\nuser GMC\nEND\nobjects 2 \nEND\n\n[% zCMyClass 0 0]\n myInt=int:12121212\n [myObject zCMyClass 0 1]\n myInt=int:34343434\n [myObject % 0 0]\n []\n [myChunk % 0 0]\n [secondPointerToMyObject % 0 0]\n []\n []\n []\n [myChunk % 0 0]\n [secondPointerToMyObject \u00a7 0 1]\n []\n []\n[]\n
Notice how secondPointerToMyObject
doesn't have any contents. The character \u00a7
tells the parser that this object already exists in the objectList, and that instead of creating a new instance, it should return an existing instance which is stored under index 1
in the objectList. This allows an instance to be referenced from multiple places, without the need to worry about duplicity.
If we used Binary or BinSafe mode, we would see a big blob of binary data instead. This would, of course, store the exact same data, although in a slightly less human-readable format.
"},{"location":"zengin/general_info/object_persistence/#final-thoughts","title":"Final thoughts","text":"We hope this helps you better understand the inner workings of ZenGin. If you want to see how Piranha Bytes went about implementing a much more advanced version of this system for their next engine, check out Genome's object persistence system.
"},{"location":"zengin/general_info/vdfs/","title":"VDFS virtual file system","text":""},{"location":"zengin/general_info/vdfs/#vdfs-virtual-file-system","title":"VDFS virtual file system","text":"VDFS is the virtual file system used by ZenGin to distribute and store many, but not all, game assets.
Learn more
If you want a more technical documentation of the VDFS format, you can find it on ZenKit site.
"},{"location":"zengin/general_info/vdfs/#loading","title":"Loading","text":""},{"location":"zengin/general_info/vdfs/#vdf","title":"VDF","text":".vdf
files can usually be found in the Data/
directory of Gothic installations and the game loads them automatically.
Volumes are loaded based on the timestamp specified inside the .vdf
file. The volumes with the latest timestamp are loaded first.
"},{"location":"zengin/general_info/vdfs/#mod","title":"MOD","text":".mod
files are stored in the Data/ModVDF/
directory and loaded when they are specified in the current game .ini
.
MyMod.ini// [...]\n[FILES]\nVDF=MyMod.mod MyMod_Textures.mod\n// [...]\n
"},{"location":"zengin/general_info/vdfs/#tools","title":"Tools","text":"The community created variety of different modding tools for work with VDFS volumes over the times, such as:
"},{"location":"zengin/general_info/vdfs/#gothicvdfs","title":"GothicVDFS","text":"Most popular tool for working with VDFS volumes. Allows viewing, extracting and building .vdf
and .mod
archives, and has CLI interface.
"},{"location":"zengin/general_info/vdfs/#vdfs-tool","title":"VDFS Tool","text":"New tool for working with VDFS volumes, created to support features introduced by Union. Apart from viewing, extracting and building .vdf
and .mod
archives, it also supports optimizing and compressing them.
"},{"location":"zengin/meshes/","title":"Meshes","text":""},{"location":"zengin/meshes/#meshes","title":"Meshes","text":"In 3D graphics, meshes are collections of vertices, edges, and faces that create 3D objects. ZenGin use meshes to create the world model and objects in the world.
Info
Not all objects that seem to be a mesh are in the \"Meshes\" category. Except every animated objects, the animation targets (like beds or doors) also belong to the Animations.
"},{"location":"zengin/meshes/#formats","title":"Formats","text":""},{"location":"zengin/meshes/#raw","title":"Raw","text":"ZenGin uses the .3ds
file format for raw source meshes. That is one of the file formats used by the Autodesk 3ds Max, which was used by the Gothic developers.
The .3ds
files can be opened with any 3D modeling software that supports this format. But, to easily import/export them with engine-specific settings, it is recommended to use Blender 2.80+ with the KrxImpExp extension.
3DS limitations
The 3DS format has some disadvantages when building levels. With very large levels such as SURFACE.3DS
, you reach the upper limit of 65,536 triangles per object that are permitted in a .3ds
file. To get around this problem, proceed as follows: simply \u201ccut\u201d the mesh into several small parts that are below the 64K triangle limit. For example, the SURFACE.3DS
was dismantled into 4 parts of roughly equal size and then completely exported. This meshes are then merged during the world compilation process into single object in the spacer.
"},{"location":"zengin/meshes/#compiled","title":"Compiled","text":"Source formats are great for editing, but can be a bit heavy for the engine use (ASCII based formats are slower to parse and work with), because of that ZenGin compiles these meshes into internal compiled formats. In the case of the world it is .MSH
format and in the case of objects in the world it is the .MRM
(multi resolution mesh) with LOD information.
"},{"location":"zengin/meshes/#tools","title":"Tools","text":""},{"location":"zengin/meshes/#krximpexp","title":"KrxImpExp","text":"Blender add-on that implements support for Gothic 3D formats.
Download
"},{"location":"zengin/meshes/#zenkit","title":"ZenKit","text":"C++ Library for loading and saving various ZenGin files (including some 3D formats).
Read More
"},{"location":"zengin/meshes/portals/","title":"Portals","text":""},{"location":"zengin/meshes/portals/#portals","title":"Portals","text":""},{"location":"zengin/meshes/portals/#introduction","title":"Introduction","text":"Static level meshes are created in modeling programs, like Blender, and then imported into the Spacer as .3ds
files. To increase rendering performance, certain contiguous areas of the level are identified as sectors during the modeling of the level meshes and separated from each other by portals. At runtime, the engine is then able to determine and exclude from the rendering process those sectors that are not visible or are far away from the current camera position due to occlusion.
Danger
The distinction between outdoor/indoor levels must be explicitly selected when compiling a level within the Spacer editor, as the conventions for equipping levels with sectors/portals for outdoor and indoor levels differ slightly.
"},{"location":"zengin/meshes/portals/#outdoor","title":"Outdoor","text":"In outdoor levels, only the interiors of buildings, caves, etc. are marked as sectors, whereas the entire open-air area itself is treated as one large \"outside\" sector.
"},{"location":"zengin/meshes/portals/#naming","title":"Naming","text":"Outdoor portals materials use the following naming convention:
P[N]:Front_Back\n
Front
is the name of the room that the portal poly normal points into. Back
is the name of the room behind the portal. The name of the \u201coutside world space\u201d is \u201c\u201d (an empty string, see example).
Material names with the prefix PN:
(\u201cN\u201d for NoFade\u201d) \u201copen\u201d visually as the camera approaches, but do not fade out like the other P:
portals. This makes sense, for example, if there is a texture with an alpha channel on such a portal.
// good technical image
"},{"location":"zengin/meshes/portals/#modeling","title":"Modeling","text":"Outdoor portals must be double-sided polygons, pointing the opposite direstions. The portal should close the area between two sectors, by touching all verticles of the sector entrance/exit. // ingame image / blender image
The sectors should be tightly closed, and contain no gaps between the walls i.e. all polys vertices should be connected to each other.
// image
Also the polys inside the sector must be connected to the walls of the setor. If some polys will be floating in the air, the engine could not render them properly.
//image
"},{"location":"zengin/meshes/portals/#ghostoccluder","title":"Ghostoccluder","text":"Ghostoccluders are polys in outdoor levels that have a material called GHOSTOCCLUDER
. Such polygons are not displayed in the game, but serve to mask areas of the level that are unnecessary for visualization (\u201cOcclusion\u201d). Unlike other polygons, Ghostoccluder polys do not depend on size, and also do not need to be segmented, as in the case of water modeling.
// image
"},{"location":"zengin/meshes/portals/#indoor","title":"Indoor","text":"In indoor levels, the entire level should be partitioned into a set of sectors. Portals are used to separate related areas, the sectors, from each other.
"},{"location":"zengin/meshes/portals/#naming_1","title":"Naming","text":"Portals must have materials whose names begin with the prefix PI:
. The rest of the name doesn't matter at the moment. The information about sector names that was previously required outdoors is no longer required here.
"},{"location":"zengin/meshes/portals/#modeling_1","title":"Modeling","text":"Portals must be convex polygons (triangle, quad, npoly). More precisely: a portal between two sectors consists of exactly one convex polygon.
//image ???
In contrast to outdoor portals, indoor portals (\u201cPI:\u201d) are single-sided. The program automatically generates the second page that is still necessary internally. They are also no longer need to be merged with the polys/verts of the static level mesh.
Portals are typically placed at passageways/doors or at tunnel beginnings and ends. They must intersect or touch all polys of the passageway where they are placed, i.e. the polys of the walls, ceilings and floor. The program therefore knows where the limitation of the sector is. However, the portal poly may NOT touch any other polys other than the directly adjacent polys of the passage. The portal poly can therefore be a little larger than the passage, but not so large that other polys that are not involved are touched. It is also important for the performance of occlusion culling that portals are not unnecessarily large. A poly of the level may penetrate a maximum of one portal poly.
// image for sure
Additional notes for modeling:
Polys are not allowed to penetrate each other All polys that cannot be seen by the player from any permitted, legal position/angle must be eliminated. It is important to ensure that there is really no space between polygons that are supposed to form a gap-free surface. For example, the bottom edge of a wall should be identical to an edge of the floor and therefore rest directly on the floor. Basically, this requirement means precise vertex placement. This could be achieved, for example, with a fine grid for vertex placement. Indoor levels (as opposed to outdoor levels) should be modeled to be completely enclosed. This means that if you (purely theoretically) filled a level with water, then the level's mesh would have no gaps or 'leaks' from which water could escape. This point is very important! Great care should be taken to ensure that there are no gaps between the polys. 'Waterproof' or 'leak-free' can be defined as follows: You cannot set up a line of sight between a point inside the level and a point outside the level. There are no 'paper walls' or polys whose invisible backside can be seen from within the level. There must be no polys whose front cannot be seen from any position within the level. Or to put it another way: no poly can have its front side in contact with the 'nothing' surrounding the level. A negative example: a cube with 4 walls facing outwards is placed in the middle of the empty space around the level \u21d2 not allowed! In general, so-called 'T-junctions' should be avoided by inserting collinear vertices into polygons. Inspired by the article about potrals from Gothic Editing Wiki \u21a9
"},{"location":"zengin/meshes/water/","title":"Water","text":""},{"location":"zengin/meshes/water/#water","title":"Water","text":"Water in ZenGin is a special surface. Therefore, there are some rules that have to be followed, to make it work properly.
"},{"location":"zengin/meshes/water/#water-modeling","title":"Water Modeling","text":"Water is created in Gothic using a double-sided tarp that is assigned a water material. This means you have to create a surface with the normal pointing upwards and the same surface facing downwards again. There must be a floor under the water tarp, otherwise you won't be able to swim. It also makes sense not to connect the double-sided water tarpaulin to the coast, otherwise the coast will follow the wave movement of the water. It's best to let the water run a little into the coast so that the wave movements don't create holes between the water and the coast.
"},{"location":"zengin/meshes/water/#segmentation","title":"Segmentation","text":"You should segment (divide) the water surface for the following reasons:
Performance: Areas are always calculated in their entirety. If the area is too large, unnecessary areas (e.g. under an island) are also calculated, which additionally deducts computing power. By segmenting you can delete areas of water that are not visible. Display error: The entire area is also displayed. However, if the end is out of sight, the water may flicker. Wave movement: The up and down movement of the water takes place at the corners of the water surfaces. If you have smaller areas, the waves are also more precise. In addition, an area that is too large may not work at all, meaning you can walk on it or even fall over. Water is a big power drain. It is advisable to make the segments towards the coast smaller and smaller so that an unnecessary number of areas in the distance do not have to be calculated, but the wave movement on the coast still looks fine enough. Here are two examples of possible segmentation of the water surface (in Blender):
In the example on the left, the water area was created from squares that get smaller the closer they are to the coast. Since Gothic automatically divides the squares into triangles anyway, the example on the right makes even more sense. The water surface was created from a hexagon and consists of whole or halved equilateral triangles. In addition, the outer boundary of the water is at a more even distance from the coast. In both examples, the segments in the middle of the island are deleted.
"},{"location":"zengin/meshes/water/#water-material-properties","title":"Water Material Properties","text":"To be able to swim in water, you need to place a water material on the double-sided water surfaces. By default, without changing any material settings the water will be frozen. To change that you have to edit zCMaterial settings in Spacer.
Tip
You can also place different water materials on the top and bottom.
The most important property - the one that tells the engine that the material is a water and player can swim in it - is matGroup. It has to be set to WATER
.
To make water look like actual water consider changing following parameters:
color - Material color. Something like 150 241 238 200
(in RGBA) will add a little transparency and blue \"glow\". texAniFPS - Speed at which the animation of the texture should be played. texAniMapDir - Speed at which the texture should be moved in the x or y direction (useful for waterfalls and rivers). Some parameters have only been available since Gothic 2:
environmentalMapping - Simulation of a reflection of the surface. environmentalMappingStrength - Strength of surface reflection. waveMode - Type of wave motion. waveSpeed - Wave speed. The higher the value, the faster the waves move. waveMaxAmplitude - Wave height. waveGridSize - Wave expansion. This article is mostly a translation of the one posted on Gothic Editing Wiki \u21a9
"},{"location":"zengin/scripts/","title":"Scripts","text":""},{"location":"zengin/scripts/#scripts","title":"Scripts","text":"ZenGin uses its own scripting language called Daedalus. It is similar to C programming language, so if you know some C programming, it will be quite easy to get started.
The Scripts
directory is where the scripts live. You will be able to find Daedalus script files - .d
extension and .src
files, that list all files to be compiled.
Daedalus scripts can be edited in any text editor. To get useful features like syntax highlighting you can use community developed tools like
Gothic Sourcer Daedalus VS Code extension "},{"location":"zengin/scripts/classes/c_info/","title":"C_INFO Daedalus class","text":""},{"location":"zengin/scripts/classes/c_info/#c_info-daedalus-class","title":"C_INFO Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library.
The C_INFO
class is used to define dialogues in the game.
"},{"location":"zengin/scripts/classes/c_info/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/Content/_intern/Classes.d
script file.
C_Info Daedalus class class C_Info\n{\n var int npc; // npc instance has the dialogue\n var int nr; // number of the dialogue (for sorting)\n var int important; // should the npc start the dialogue automatically\n var func condition; // condition function\n var func information; // function called on selecting the dialogue\n var string description; // text in the dialogue box\n var int trade; // should the dialogue show the trade window\n var int permanent; // should the dialogue be permanent or only one time deal\n};\n
"},{"location":"zengin/scripts/classes/c_info/#class-members","title":"Class members","text":"Variable Type Description npc int npc instance to have the dialogue nr int dialogue order number important int npc addresses player automatically condition func condition function whether the dialogue is shown or not information func function called on dialogue selection - contains the dialogue lines and other logic description string text shown in the dialogue box trade int is it a trade dialogue permanent int does the dialogue stay after being played once"},{"location":"zengin/scripts/classes/c_info/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_info/#npc","title":"npc","text":"Sets what NPC will have this dialogue instance. Set an NPC instance.
instance Info_Diego_Gamestart (C_INFO)\n{\n npc = PC_Thief; // NPC instance for Diego\n // ...\n};\n
"},{"location":"zengin/scripts/classes/c_info/#nr","title":"nr","text":"The nr
member variables determines the order of shown dialogues. Dialogues are ordered in the ascending order - instances with higher nr
are below instances with lower nr
.
instance Info_Diego_Gamestart (C_INFO)\n{\n // ...\n nr = 1;\n // ...\n};\n
Note
This is why the end dialogues usually have nr = 999;
this is the highest number out of any dialogues therefore will always show up at the bottom. (999 is not the highest number the nr
can store, it is just considered the highest number, as there will hardly be 998 dialogue instances for a single character)
"},{"location":"zengin/scripts/classes/c_info/#important","title":"important","text":"The important
member variable determines whether the NPC will automatically address the player or not.
important = TRUE
- the NPC will address the player important = FALSE
- the player has to talk to the NPC When important
is set to TRUE
, the description is not needed since the dialogue is never shown in the dialogue box.
Info
If there are multiple important dialogues that satisfy their condition function, they will be played in the order specified by nr
.
Tip
important
variable is of the type integer, and it is initialized by the engine to the value of 0
. If you do not want your dialogue to be important, you can omit the important
member variable since it will be initialized to 0
by the engine.
"},{"location":"zengin/scripts/classes/c_info/#condition","title":"condition","text":"Condition function with signature func int f()
. If the function returns TRUE
the dialogue is displayed, if it returns FALSE
it is not displayed. The function name does not have to follow a particular naming convention, but a naming convention is used throughout all the Gothic scripts: {DialogueName}_Condition
.
Conditioned dialogueUnconditioned dialogue instance Info_Diego_Gamestart (C_INFO)\n{\n // ...\n condition = Info_Diego_Gamestart_Condition;\n // ...\n};\n\nfunc int Info_Diego_Gamestart_Condition()\n{\n if (Kapitel < 2) // Show only when chapter is less than 2\n {\n return TRUE;\n };\n return FALSE; // Not needed, but added for readability\n};\n
instance Info_Diego_EXIT_Gamestart(C_INFO)\n{\n // ...\n condition = Info_Diego_EXIT_Gamestart_Condition;\n // ...\n};\n\nfunc int Info_Diego_EXIT_Gamestart_Condition()\n{\n return TRUE; // or return 1;\n};\n
Tip
It is unnecessary to return FALSE
from dialogue conditions, but in other cases it can very rarely cause subtle bugs. It is thus good practice to always return some value, even if that is FALSE
.
"},{"location":"zengin/scripts/classes/c_info/#information","title":"information","text":"The information
function contains the function name (without double quotes \"\"
as func
is a type in Daedalus) that is called when the dialogue option is selected. It contains the lines NPCs will say, items that will be transferred, quests related logic and much more. The function name does not have to follow a particular naming convention, but a naming convention is used throughout all the Gothic scripts: {DialogueName}_Info
.
instance Info_Diego_Gamestart (C_INFO)\n{\n npc = PC_Thief;\n nr = 1;\n condition = Info_Diego_Gamestart_Condition;\n information = Info_Diego_Gamestart_Info;\n permanent = FALSE;\n important = TRUE;\n};\n\nfunc int Info_Diego_Gamestart_Condition()\n{\n if (Kapitel < 2)\n {\n return TRUE;\n };\n return FALSE;\n};\n\nfunc void Info_Diego_Gamestart_Info()\n{\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_00\"); //I'm Diego.\n AI_Output(hero,self,\"Info_Diego_Gamestart_15_01\"); //I'm...\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_02\"); //I'm not interested in who you are. You've just arrived. I look after the new arrivals. That's all for now.\n AI_Output(self,hero,\"Info_Diego_Gamestart_11_03\"); //If you plan to stay alive for a while, you should talk to me. But of course I won't keep you from choosing your own destruction. Well, what do you think?\n\n B_Kapitelwechsel(1); // Show the chapter 1 screen\n};\n
"},{"location":"zengin/scripts/classes/c_info/#description","title":"description","text":"Specify a string that will be shown in the dialogue window.
instance DIA_XARDAS_GMC(C_INFO)\n{\n // ...\n description = \"Hello, is this the GMC site?\";\n};\n
"},{"location":"zengin/scripts/classes/c_info/#trade","title":"trade","text":"If trade
is set to TRUE
the trading interface will be launched after the content information
function is finished.
Fisk's trade dialogueinstance Stt_311_Fisk_Trade (C_INFO)\n{\n npc = Stt_311_Fisk;\n nr = 800;\n condition = Stt_311_Fisk_Trade_Condition;\n information = Stt_311_Fisk_Trade_Info;\n permanent = TRUE;\n description = \"Show me your goods.\";\n trade = TRUE;\n};\n\nfunc int Stt_311_Fisk_Trade_Condition()\n{\n return TRUE;\n};\n\nfunc void Stt_311_Fisk_Trade_Info()\n{\n AI_Output (other, self, \"Stt_311_Fisk_Trade_15_00\"); //Show me your goods.\n};\n
Trivia
Trade manager has been added to ZenGin not that long before the release of Gothic 1 (as discussed and discovered on Phoenix the Game Discord server with the acquisition of Gothic version 0.94k
). In version 0.94 the trade manager worked quite differently and used a special (nowadays unused) Daedalus class C_ItemReact
.
"},{"location":"zengin/scripts/classes/c_info/#permanent","title":"permanent","text":"Dialogues with permanent = TRUE
do not disappear after the dialogue is played. This is used for dialogues where you ask for directions or flavor dialogues for unnamed NPCs.
Bug
Frequently used external function Npc_KnowsInfo
which returns true if the dialogue instance has been played has had a bug in the implementation for a long time. This bug made it impossible to use this function with dialogue instances with permanent = TRUE
as it would always return FALSE
. This has been fixed in Union 1.0m
.
"},{"location":"zengin/scripts/classes/c_info/#lego","title":"LeGo","text":"LeGo implements a lot of useful functions for dialogues. It makes it possible to create Trialogues and change NPCs behaviour by Dialoggestures. Moreover, any Daedalus function can be added to NPCs AI queue via the AI_Function package.
"},{"location":"zengin/scripts/classes/c_info/#zparserextender","title":"zParserExtender","text":"zParserExtender implements some Quality of Life features for dialogues. More information can be found in Dialogue constants article.
"},{"location":"zengin/scripts/classes/c_info/#af-script-packet","title":"AF Script Packet","text":"Enhanced Info Manager (implemented using Ikarus and LeGo) adds tons of customizations and additional features to dialogues. More information can be found in the AFSP Enhanced Information Manager article.
"},{"location":"zengin/scripts/classes/c_item/","title":"C_ITEM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_item/#c_item-daedalus-class","title":"C_ITEM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
The C_ITEM
class is used to define new items in the game.
"},{"location":"zengin/scripts/classes/c_item/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/Content/_intern/Classes.d
script file.
C_Item Daedalus class class C_Item\n{\n // For all Items\n var int id; // ID of the item\n var string name; // Name of the item\n var string nameID; // Name ID\n var int hp; // Current health of the item\n var int hp_max; // Maximum health of the item\n\n var int mainflag; // Item category flag\n var int flags; // Item type flag\n var int weight; // Weight of the item\n var int value; // Value of the item\n\n // For weapons\n var int damageType; // Damage type\n var int damageTotal; // Total amount of damage\n var int damage[DAM_INDEX_MAX]; // Array of damage types\n\n // For armours\n var int wear; // Flag to specify where to wear an item\n var int protection[PROT_INDEX_MAX]; // Protection array of different damage types\n\n // For food\n var int nutrition; // The amount of HP healed\n\n // Ben\u00f6tigte Attribute zum Benutzen des Items\n var int cond_atr[3]; // Array of NPC attributes needed to equip the item\n var int cond_value[3]; // Array of values corresponding to the cond_atr array\n\n // Attributes to be changed on equip\n var int change_atr[3]; // Array of attributes that will be changed on equip\n var int change_value[3]; // Array of values of the attributes defined in change_atr\n\n // Parser functions\n var func magic;\n var func on_equip; // Called on equpping an item\n var func on_unequip; // Called on unequipping an item\n var func on_state[4];\n\n var func owner; // Owner of the item: instance name\n var int ownerGuild; // Owner of the item: guild\n var int disguiseGuild; // NPC guild set when equipping an item\n\n // 3DS model file\n var string visual; // Item model file\n\n // NPC mesh change, when equipping an item\n var string visual_change; // .asc file\n var string effect; // Effect instance\n\n var int visual_skin; // Texture variation\n\n var string scemeName; // Animation sceme name\n var int material; // Material of the object\n\n var int munition; // Ammo instance\n\n var int spell; // ID if the spell that this item does\n var int range; // Range of the weapon\n\n var int mag_circle; // Circle of magic needed to use this item\n\n var string description; // The name of the item shown in the preview box\n var string text[ITM_TEXT_MAX]; // Array of string describing the item (left side)\n var int count[ITM_TEXT_MAX]; // Array of integers (the right side)\n\n // Parameters for displaying items in the inventory\n var int inv_zbias // How far away is the item from the screen\n var int inv_rotx // X-axis rotation\n var int inv_roty // Y-axis rotation\n var int inv_rotz // Z-axis rotation\n var int inv_animate // Should the item rotate in the inventory\n};\n
It has many member variables but not all of them are used for every item. It is not necessary to define every one of these variables for every item as it was discussed on InsideGothic.
"},{"location":"zengin/scripts/classes/c_item/#class-members","title":"Class members","text":"A selection of the most important class members.
"},{"location":"zengin/scripts/classes/c_item/#change_atr--change_value","title":"change_atr & change_value","text":"change_atr
stores the attributes that will be changed by the amount specified in change_value
.
NPCs have these attributes:
const int ATR_HITPOINTS = 0; // Hit points\nconst int ATR_HITPOINTS_MAX = 1; // Max hitpoints\nconst int ATR_MANA = 2; // Mana\nconst int ATR_MANA_MAX = 3; // Max mana\n\nconst int ATR_STRENGTH = 4; // Strength\nconst int ATR_DEXTERITY = 5; // Dexterity\nconst int ATR_REGENERATEHP = 6; // HP regeneration per second\nconst int ATR_REGENERATEMANA = 7; // Mana regeneration per second\n
This can be used on all equipable items to change the attributes. As an example we can create a sword that has a 10 point dexterity bonus.
instance ItMw_testSword (C_Item)\n{\n // some code\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n // some code\n};\n
Warning
Do not change ATR_HITPOINTS
, ATR_MANA
, ATR_HITPOINTS_MAX
or ATR_MANA_MAX
as it will result in unwanted behaviour with max health or max mana.
You can change ATR_HITPOINTS_MAX
and ATR_MANA_MAX
attributes in on_equip and on_unequip
"},{"location":"zengin/scripts/classes/c_item/#cond_atr--cond_value","title":"cond_atr & cond_value","text":"cond_atr
stores the attributes that will be checked as a requirement to equip an item, the amount specified in cond_value
.
The next example sword is equipable only if the NPC has at least 5 strength. If the requirements are not met G_CanNotUse()
is called.
instance ItMw_testSword (C_Item)\n{\n // some code\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n // some code\n};\n
Try injecting the code below zParserExtender to test it in game right away. It is compatible with G2NotR.
instance ItMw_testSword (C_Item)\n{\n name = TXT_Spells[10]; // demonstrates the usage of direct constr array access\n\n mainflag = ITEM_KAT_NF;\n flags = ITEM_SWD;\n material = MAT_METAL;\n\n value = 10;\n\n damageTotal = 10;\n damagetype = DAM_EDGE;\n range = 100;\n\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n\n visual = \"ItMw_010_1h_Sword_short_01.3DS\";\n\n description = name;\n\n TEXT[2] = NAME_Damage; COUNT[2] = damageTotal;\n TEXT[3] = NAME_Str_needed; COUNT[3] = cond_value[2];\n TEXT[4] = NAME_OneHanded;\n TEXT[5] = NAME_Value; COUNT[5] = value;\n};\n
To insert it into the game use insert ItMw_testSword
in console."},{"location":"zengin/scripts/classes/c_item/#text--count-arrays","title":"text & count arrays","text":"These two arrays are used to put information into the item information box. The maximum number of lines is 6. This is defined in the engine, but for script side class definition is declared in the scripts too.
const int ITM_TEXT_MAX = 6;\n
This example shows an item with all elements of TEXT
and COUNT
array filled. Note
Please notice the last COUNT
element. It did not take the value we entered, but shows 10
which is the value
of the item. This behaviour can be changed with Ikarus or Union.
You can find the code below
instance ItMw_testSword (C_Item)\n{\n name = TXT_Spells[10];\n\n mainflag = ITEM_KAT_NF;\n flags = ITEM_SWD;\n material = MAT_METAL;\n\n value = 10;\n\n damageTotal = 10;\n damagetype = DAM_EDGE;\n range = 100;\n\n cond_atr[2] = ATR_STRENGTH;\n cond_value[2] = 5;\n\n change_atr[0] = ATR_DEXTERITY;\n change_value[0] = 10;\n\n visual = \"ItMw_010_1h_Sword_short_01.3DS\";\n\n description = name;\n\n TEXT[0] = \"Line 0\"; COUNT[0] = 0; \n TEXT[1] = \"Line 1\"; COUNT[1] = 1; \n TEXT[2] = \"Line 2\"; COUNT[2] = 2; \n TEXT[3] = \"Line 3\"; COUNT[3] = 3; \n TEXT[4] = \"Line 4\"; COUNT[4] = 34;\n TEXT[5] = \"Line 5\"; COUNT[5] = 35;\n};\n
"},{"location":"zengin/scripts/classes/c_item/#description--name","title":"description & name","text":"description
- determines the name of the item in the inventory
name
- determines the focus name of the item in the world
In the scripts you often find that the description is assigned the value of name
.
instance ItMw_testSword (C_Item)\n{\n name = \"New amazing sword\";\n // ...\n description = name; // description now has the same value as ' // ...name'\n // ...\n};\n
This is used in the case where you want to show the name of the item on focus too. There is a second way used in the scripts though with, for example,magic scrolls - the focus name in the world is \"Scroll\" and in inventory the scroll carries the name of the spell. This is how it is done:
instance ItSc_InstantFireball (C_Item)\n{\n name = NAME_Spruchrolle; // const string = \"Scroll\"\n // ...\n description = NAME_SPL_InstantFireball; // const string = \"Fireball\"\n // ...\n};\n
"},{"location":"zengin/scripts/classes/c_item/#hp--hp_max","title":"hp & hp_max","text":"Both of these parameters are unused.
Trivia
In alpha ZenGin versions the player was able to destroy objects. This feature was abandoned during the course of the development. This video shows the reconstruction of this feature.
"},{"location":"zengin/scripts/classes/c_menu/","title":"C_MENU Daedalus class","text":""},{"location":"zengin/scripts/classes/c_menu/#c_menu-daedalus-class","title":"C_MENU Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_Menu
is responsible for the behavior and properties of the game menus (options, save etc.).
"},{"location":"zengin/scripts/classes/c_menu/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Menu.d
script file.
C_Menu Daedalus class class C_Menu \n{\n var string backPic; // Menu background image\n var string backWorld; // Background ZEN-world of the game menu (Not used)\n var int posx; // The top left point of the menu on the screen horizontally (X-axis)\n var int posy; // The top left point of the menu on the screen vertically (Y-axis)\n var int dimx; // Menu width in virtual coordinates\n var int dimy; // Menu height in virtual coordinates\n var int alpha; // Menu transparency\n var string musicTheme; // Music track of the menu\n var int eventTimerMSec; // trigger time for the event EVENT_TIMER\n var string items[150]; // Menu items\n var int flags; // Menu flags\n var int defaultOutGame; // Menu item highlighted by default when the game is not running\n var int defaultInGame; // Menu item highlighted by default when the game is running\n};\n
"},{"location":"zengin/scripts/classes/c_menu/#class-members","title":"Class members","text":"Variable Type Description backPic string Menu background image backWorld string Background ZEN-world of the game menu (Not used) posx int The top left point of the menu on the screen horizontally (X-axis) posy int The top left point of the menu on the screen vertically (Y-axis) dimx int Menu width in virtual coordinates dimy int Menu height in virtual coordinates alpha int Menu transparency musicTheme string Music track of the menu eventTimerMSec int The timer that triggered the event in seconds items string Menu items flags int Menu flags defaultOutGame int Menu item highlighted by default when the game is not running defaultInGame int Menu item highlighted by default when the game is running"},{"location":"zengin/scripts/classes/c_menu/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_menu/#backpic","title":"backPic","text":"backPic
is just a name of background image of the menu in .tga
format.
"},{"location":"zengin/scripts/classes/c_menu/#backworld","title":"backWorld","text":"Deprecated setting
The background world of the game menu in .ZEN
format.
"},{"location":"zengin/scripts/classes/c_menu/#posx","title":"posx","text":"The horizontal position of the top left point of the menu on the screen, in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#posy","title":"posy","text":"The vertical position of the top left point of the menu on the screen, in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#dimx","title":"dimx","text":"Menu width in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#dimy","title":"dimy","text":"Menu height in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menu/#alpha","title":"alpha","text":"Menu transparency. Accepts values \u200b\u200bfrom 0 to 255. Without the backPic
property specified, the value of this parameter is ignored.
Note
Texture transparency can only be adjusted if the texture has an alpha channel.
"},{"location":"zengin/scripts/classes/c_menu/#musictheme","title":"musicTheme","text":"Music theme of the menu.
instance MENU_MAIN(C_MENU_DEF)\n{\n ...\n musictheme = \"SYS_Menu\";\n ...\n};\n
All instances of musical themes are stored in a file Scripts/System/Music/MusicInst.d
"},{"location":"zengin/scripts/classes/c_menu/#eventtimermsec","title":"eventTimerMSec","text":"Defines the trigger time for the event EVENT_TIMER
in seconds.
The list of constants for all menu events is described in the file Scripts/System/_intern/Menu.d
const int EVENT_UNDEF = 0; // Undefined\nconst int EVENT_EXECUTE = 1; // Process start event\nconst int EVENT_CHANGED = 2; // Menu parameter change event\nconst int EVENT_LEAVE = 3; // Menu item focus loss event\nconst int EVENT_TIMER = 4; // Timer fire event\nconst int EVENT_CLOSE = 5; // Menu close event\nconst int EVENT_INIT = 6; // Initialization event\nconst int EVENT_SEL_PREV = 7; // Select event of the previous menu item\nconst int EVENT_SEL_NEXT = 8; // Select event of the next menu item\n
"},{"location":"zengin/scripts/classes/c_menu/#items","title":"items","text":"An array of items belonging to this menu. It is possible to use up to 150 items in one menu. The same elements can be used for different menus. The element instance is specified as the value.
// Menu\ninstance MENU_MAIN(C_MENU_DEF)\n{\n ...\n items[0] = \"MENUITEM_MAIN_HEADLINE\"; \n items[1] = \"MENUITEM_MAIN_HEADLINE2\";\n items[2] = \"MENUITEM_MAIN_NEWGAME\";\n ...\n};\n\n// Menu elements: labels, checkboxes, sliders, etc.\n\ninstance MENUITEM_MAIN_HEADLINE(C_MENU_ITEM_DEF)\n{\n ...\n};\n\ninstance MENUITEM_MAIN_HEADLINE2(C_MENU_ITEM_DEF)\n{\n ...\n};\n\ninstance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n ...\n};\n
"},{"location":"zengin/scripts/classes/c_menu/#flags","title":"flags","text":"Menu flags.
The list of flag constants can be found in the file Scripts/System/_intern/Menu.d
const int MENU_OVERTOP = 1; // Show menu over previous menu or in game\nconst int MENU_EXCLUSIVE = 2; // Close all previous menus. Only the active menu is displayed\nconst int MENU_NOANI = 4; // No animation\nconst int MENU_DONTSCALE_DIM = 8; // Don't Scale Menu Sizes\nconst int MENU_DONTSCALE_POS = 16; // Empty flag\nconst int MENU_ALIGN_CENTER = 32; // Center Align Menu\nconst int MENU_SHOW_INFO = 64; // Display information at the bottom of the description menu from menu items text[1]\n
MENU_OVERTOP - Flag to display the menu over the previous menu. It is not advisable to use with a transparent menu. MENU_EXCLUSIVE - Hide all menus except the active one. When closed, the previous menu is restored. MENU_NOANI - Animation of minimizing and maximizing windows. The game is mainly used for dialogue windows. You can't enable or disable the animation of dialog windows through scripts. This is done using the animatedWindows
setting in the Gothic.ini file. MENU_DONTSCALE_DIM - Scale the menu to fit 640x480 resolution. MENU_DONTSCALE_POS - Empty flag. Not used. MENU_ALIGN_CENTER - Align the menu to the center of the screen. MENU_SHOW_INFO - Display information at the bottom of menu description from menu item text[1]
. "},{"location":"zengin/scripts/classes/c_menu/#defaultoutgame","title":"defaultOutGame","text":"The menu item that is highlighted by default when the game is not running.
A value of -1 enables automatic selection of the first selectable element.
Items with the ~IT_SELECTABLE
flag are not selected.
"},{"location":"zengin/scripts/classes/c_menu/#defaultingame","title":"defaultInGame","text":"Menu item highlighted by default when the game is running.
A value of -1 enables automatic selection of the first selectable element.
Items with the ~IT_SELECTABLE
flag are not selected.
"},{"location":"zengin/scripts/classes/c_menuitem/","title":"C_MENU_ITEM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_menuitem/#c_menu_item-daedalus-class","title":"C_MENU_ITEM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_Menu_Item
describes the elements of the game menu (sliders, checkboxes, buttons, etc.) .
"},{"location":"zengin/scripts/classes/c_menuitem/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Menu.d
script file.
C_Menu_Item Daedalus class CONST INT MAX_USERSTRINGS = 10;\nCONST INT MAX_ITEMS = 150;\nCONST INT MAX_EVENTS = 10;\nCONST INT MAX_SEL_ACTIONS = 5;\nCONST INT MAX_USERVARS = 4;\n\nclass C_Menu_Item\n{\n var string fontName; // Font of the menu item.\n var string text[MAX_USERSTRINGS]; // Text of the interface element.\n var string backPic; // Background image of menu items.\n var string alphaMode; // Transparency blending mode of menu items.\n var int alpha; // Transparency of the menu item.\n var int type; // Type of the interface element.\n var int onSelAction[MAX_SEL_ACTIONS]; // Array of commands executed when selecting the menu item.\n var string onSelAction_S[MAX_SEL_ACTIONS]; // Arguments for commands specified in the onSelAction property.\n var string onChgSetOption; // Gothic.ini file parameter modified by this menu item.\n var string onChgSetOptionSection; // Section of the Gothic.ini file where the modified parameter is located.\n var func onEventAction[MAX_EVENTS]; // Call the required function by a constant identifier.\n var int posx; // Top-left point of the menu item on the screen horizontally (X-axis).\n var int posy; // Top-left point of the menu item on the screen vertically (Y-axis).\n var int dimx; // Width of the menu item in virtual coordinates.\n var int dimy; // Height of the menu item in virtual coordinates.\n var float sizeStartScale; // Initial size of the item. Not used.\n var int flags; // Flags of the menu item.\n var float openDelayTime; // Delay before opening the item. Not used.\n var float openDuration; // Opening time. Not used.\n var float userFloat[MAX_USERVARS]; // Digital settings of menu items.\n var string userString[MAX_USERVARS]; // String settings of menu items.\n var int frameSizeX; // Text offset inside the frame on the X-axis.\n var int frameSizeY; // Text offset inside the frame on the Y-axis.\n var string hideIfOptionSectionSet; // Section of Gothic.ini file where the option determining the display of this menu item is located.\n var string hideIfOptionSet; // Gothic.ini file parameter determining the display of this menu item.\n var int hideOnValue; // Value of the Gothic.ini file parameter at which this interface element is not displayed.\n}; \n
"},{"location":"zengin/scripts/classes/c_menuitem/#class-members","title":"Class members","text":"Property Type Description fontName string Font of the menu item. text string Text of the interface element. backPic string Background image of menu items. alphaMode string Transparency blending mode of menu items. alpha int Transparency of the menu item. type int Type of the interface element. onSelAction int Array of commands executed when selecting the menu item. onSelAction_S string Arguments for commands specified in the onSelAction property. onChgSetOption string Gothic.ini file parameter modified by this menu item. onChgSetOptionSection string Section of the Gothic.ini file where the modified parameter is located. onEventAction Func Call the required function by a constant identifier. posx int Top-left point of the menu item on the screen horizontally (X-axis). posy int Top-left point of the menu item on the screen vertically (Y-axis). dimx int Width of the menu item in virtual coordinates. dimy int Height of the menu item in virtual coordinates. sizeStartScale float Initial size of the item. Not used. flags int Flags of the menu item. openDelayTime float Delay before opening the item. Not used. openDuration float Opening time. Not used. userFloat float Digital settings of menu items. userString string String settings of menu items. frameSizeX int Text offset inside the frame on the X-axis. frameSizeY int Text offset inside the frame on the Y-axis. hideIfOptionSectionSet string Section of Gothic.ini file where the option determining the display of this menu item is located. hideIfOptionSet string Gothic.ini file parameter determining the display of this menu item. hideOnValue int Value of the Gothic.ini file parameter at which this interface element is not displayed."},{"location":"zengin/scripts/classes/c_menuitem/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_menuitem/#fontname","title":"fontName","text":"*.TGA
file defining the font of the displayed text of the menu item.
To create a color change effect, two fonts are needed:
The first font is specified in the fontName
field and is used by default. The second font with the suffix _Hi
is used to replace the text on the active (selected) element. This creates a highlighting effect.
"},{"location":"zengin/scripts/classes/c_menuitem/#text","title":"text","text":"Text inside a menu item.
Used to determine possible values \u200b\u200bfor game settings. See onChgSetOptionSection.
Also used to display hints about the item at the bottom of the menu when the MENU_SHOW_INFO
flag is set.
// Text displayed in the element\n\ntext[0] = \"New Game\";\n\n// Text in the interface element responsible for game settings\n// One of the presented options is displayed\n\ntext[0] = \"off|on\";\n\n// Tooltip for the selected element\n// Index 1 is used for tooltips, not 0\n\ntext[1] = \"Start a new adventure\";\n
"},{"location":"zengin/scripts/classes/c_menuitem/#backpic","title":"backPic","text":"Background image of the menu item in *.TGA
format.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n backpic = \"Inv_Slot_Highlighted.tga\";\n}\n
"},{"location":"zengin/scripts/classes/c_menuitem/#alphamode","title":"alphaMode","text":"Texture transparency blending mode. Used in conjunction with the alpha property. This parameter's value is ignored if the backPic property is not specified.
Supported modes:
MAT_DEFAULT
Uses the standard texture. If the material has an alpha channel, it will be transparent; otherwise, it will be opaque.
NONE
Transparency is not used unless the texture itself is transparent.
BLEND
Blends the alpha channel of the texture with the background.
ADD
Adds the alpha channel of the texture to the background.
SUB
Subtracts the alpha channel of the texture from the background.
MUL
and MUL2
Multiplies the alpha channel of the texture by the background.
"},{"location":"zengin/scripts/classes/c_menuitem/#alpha","title":"alpha","text":"Menu element transparency. Accepts values \u200b\u200bfrom 0 to 255. Without specifying the backPic property, the value of this parameter is ignored.
The alpha channel rendering mode is determined using the alphaMode property.
"},{"location":"zengin/scripts/classes/c_menuitem/#type","title":"type","text":"Interface element type. Some interface elements have their own settings determined by the userFloat and userString properties.
Constants for menu item types are described in the file Scripts/System/_intern/Menu.d
.
CONST INT MENU_ITEM_UNDEF = 0; // Undefined\nCONST INT MENU_ITEM_TEXT = 1; // Text\nCONST INT MENU_ITEM_SLIDER = 2; // Slider\nCONST INT MENU_ITEM_INPUT = 3; // Input field\nCONST INT MENU_ITEM_CURSOR = 4; \nCONST INT MENU_ITEM_CHOICEBOX = 5; // Checkbox\nCONST INT MENU_ITEM_BUTTON = 6; // Button\nCONST INT MENU_ITEM_LISTBOX = 7; // Frame\n
MENU_ITEM_UNDEF
Undefined element type. Not used in scripts.
MENU_ITEM_TEXT
Menu item type \"Text\". Text can be multiline by setting the IT_MULTILINE
flag.
MENU_ITEM_SLIDER
Menu item type \"Slider\". Additional settings are provided for the slider.
userFloat[0]
property determines the number of divisions for the slider. userFloat[1]
property determines the width of the slider. userString[0]
property determines the background image for the slider thumb. INSTANCE MENUITEM_AUDIO_MUSICVOL_SLIDER(C_MENU_ITEM_DEF)\n{\n backPic = MENU_SLIDER_BACK_PIC;\n type = MENU_ITEM_SLIDER; // Type: Slider\n // [...]\n onChgSetOption = \"musicVolume\"; // INI file parameter\n onChgSetOptionSection = \"SOUND\"; // INI file section\n userFloat[0] = 15; // Number of slider positions\n userString[0] = MENU_SLIDER_POS_PIC; // Background image of the slider\n // [...]\n};\n
MENU_ITEM_INPUT
This type of element is intended for entering control keys during configuration, as well as for entering the name of the save in the corresponding menu.
MENU_ITEM_CURSOR
Deprecated element type. Not used in scripts.
MENU_ITEM_CHOICEBOX
\"SELECT\" type allowing the selection of one of the available values.
MENU_ITEM_BUTTON
Button. Not used in scripts.
The userString[0]
property determines which image will be used for the disabled button. The backPic property is responsible for the background image of the enabled button. MENU_ITEM_LISTBOX
Menu item type used in the \"Quest Log\" menu.
The userString[0]
property determines which task list will be displayed in this element. userstring[0] = \"CURRENTMISSIONS\";\nuserstring[0] = \"OLDMISSIONS\";\nuserstring[0] = \"FAILEDMISSIONS\";\nuserstring[0] = \"LOG\";\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onselaction","title":"onSelAction","text":"Array of commands executed when selecting the menu item.
Each command receives parameters in the onSelAction_S
property.
Constants are described in the file Scripts/System/_intern/Menu.d
.
CONST INT SEL_ACTION_UNDEF = 0; // No action. Used when setting game parameters, calling functions...\nCONST INT SEL_ACTION_BACK = 1; // Return to the previous menu or game\nCONST INT SEL_ACTION_STARTMENU = 2; // Open a menu\nCONST INT SEL_ACTION_STARTITEM = 3; // Special command for save slots\nCONST INT SEL_ACTION_CLOSE = 4; // Close menu or game\nCONST INT SEL_ACTION_CONCOMMANDS = 5; // Execute console command\nCONST INT SEL_ACTION_PLAY_SOUND = 6; // Play sound from C_SFX instance\nCONST INT SEL_ACTION_EXECCOMMANDS = 7; // Execute command specified in the onSelAction_S field using RUN or EFFECT commands\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onselaction_s","title":"onSelAction_S","text":"Arguments for commands specified in the onSelAction
property.
Below are commands and their arguments:
SEL_ACTION_UNDEF
This command has no arguments and is mostly used in options and for calling script functions.
instance MENUITEM_MAIN_CREDITS(C_MENU_ITEM_DEF)\n{\n text[0] = \"Credits\";\n // [...]\n onselaction[0] = SEL_ACTION_UNDEF;\n oneventaction[1] = showcredits;\n};\n\nfunc int showcredits()\n{\n PlayVideo(\"credits.bik\");\n PlayVideo(\"credits2.bik\");\n return 1;\n};\n
SEL_ACTION_BACK
This command has no arguments. It returns to the previous menu or the game.
instance MENUITEM_MAIN_RESUME(C_MENU_ITEM_DEF)\n{\n text[0] = \"Resume\";\n text[1] = \"Resume the current game\";\n // [...]\n onselaction[0] = SEL_ACTION_BACK;\n};\n
SEL_ACTION_STARTMENU
The argument for this command is the menu instance. The specified menu will be displayed.
instance MENUITEM_MAIN_EXIT(C_MENU_ITEM_DEF)\n{\n text[0] = \"Quit Game\";\n text[1] = \"Leave the world of Gothic II\";\n onselaction[0] = SEL_ACTION_STARTMENU;\n onselaction_s[0] = \"MENU_LEAVE_GAME\";\n // [...]\n};\n\ninstance MENU_LEAVE_GAME(C_MENU_DEF)\n{\n // [...]\n};\n
SEL_ACTION_STARTITEM
The argument is an interface element serving as a slot for saving the game.
INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_STARTITEM;\n onSelAction_S[0]= \"MENUITEM_SAVE_SLOT1\";\n onSelAction[1] = SEL_ACTION_CLOSE;\n onSelAction_S[1]= \"SAVEGAME_SAVE\";\n};\n
SEL_ACTION_CLOSE
The closing menu command supports the following arguments:
NEW_GAME
Start a new game.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) \n{\n // [...]\n text[0] = \"New Game\";\n text[1] = \"Start a new adventure\";\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"NEW_GAME\";\n};\n
LEAVE_GAME
Exit the game.
INSTANCE MENUITEM_LEAVE_GAME_YES(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Yes.\";\n text[1] = \"Yes, I'll be back!\";\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"LEAVE_GAME\";\n};\n
SAVEGAME_SAVE
Save the game to the selected slot and return to the game.
INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_STARTITEM;\n onSelAction_S[0]= \"MENUITEM_SAVE_SLOT1\";\n onSelAction[1] = SEL_ACTION_CLOSE;\n onSelAction_S[1]= \"SAVEGAME_SAVE\";\n};\n
SAVEGAME_LOAD
Load the game from the selected slot and return to the game.
INSTANCE MENUITEM_LOAD_SLOT1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[0] = SEL_ACTION_CLOSE;\n onSelAction_S[0]= \"SAVEGAME_LOAD\";\n};\n
SEL_ACTION_CONCOMMANDS
The argument is a console commands.
INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[1] = SEL_ACTION_CONCOMMANDS;\n onSelAction_S[1]= \"goto pos 0 0 0\";\n};\n
SEL_ACTION_PLAY_SOUND
The argument is an C_SFX class instance.
INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF)\n{\n // [...]\n onSelAction[1] = SEL_ACTION_PLAY_SOUND;\n onSelAction_S[1]= \"LevelUp\";\n};\n
SEL_ACTION_EXECCOMMANDS
There are two supported executable commands: RUN
and EFFECTS
.
RUN
Indicates the instance of the menu element that is used to select the key.
INSTANCE MENU_ITEM_KEY_UP(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Forward\";\n text[1] = \"press DEL key to empty slot and RETURN to define\";\n onSelAction[0] = SEL_ACTION_EXECCOMMANDS;\n onSelAction_S[0]= \"RUN MENU_ITEM_INP_UP\";\n};\n\nINSTANCE MENU_ITEM_INP_UP(C_MENU_ITEM_DEF)\n{\n // [...]\n text[1] = \"Please press the desired key for this action.\";\n type = MENU_ITEM_INPUT;\n onChgSetOption = \"keyUp\";\n onChgSetOptionSection = \"KEYS\";\n};\n
EFFECTS
Specifies the menu item instance to which the focus switches.
INSTANCE MENU_ITEM_SEL_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n text[0] = \"Current\\nQuests\";\n // [...]\n onSelAction[0] = SEL_ACTION_EXECCOMMANDS;\n onSelAction_S[0]= \"EFFECTS MENU_ITEM_LIST_MISSIONS_ACT\"; \n};\n\ninstance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n type = MENU_ITEM_LISTBOX; \n text[0] = \"Act Missions\";\n // [...]\n userString[0] = \"CURRENTMISSIONS\"; \n};\n
There are also two commands, SETDEFAULT
and SETALTERNATIVE
, which set control settings. The first restores default settings, and the second uses alternative character control settings.
"},{"location":"zengin/scripts/classes/c_menuitem/#onchgsetoption","title":"onChgSetOption","text":"Parameter of the Gothic.ini
file that will be modified by this menu item.
instance MENUITEM_GAME_FIGHTFOCUS_CHOICE(C_MENU_ITEM_DEF)\n{\n text[0] = \"none|box|lighten|both\";\n // [...]\n onChgSetOption = \"highlightMeleeFocus\"; // INI parameter\n onChgSetOptionSection = \"GAME\"; // INI section\n // [...]\n};\n
The text[0]
property of such an element usually specifies possible values of the modified parameter. Values are listed using the |
symbol.
Make sure that the number of parameter options in the menu corresponds to the number of options in the Gothic.ini
file.
highlightMeleeFocus=2\n; ... here you can turn on an optional focus highlight effect during fighting\n
"},{"location":"zengin/scripts/classes/c_menuitem/#onchgsetoptionsection","title":"onChgSetOptionSection","text":"The section of the Gothic.ini file in which the parameter being changed is located.
See onChgSetOption above.
"},{"location":"zengin/scripts/classes/c_menuitem/#oneventaction","title":"onEventAction","text":"Allows a user to call a function on a specified event.
The list of constants is described in the file Scripts/System/_intern/Menu.d
.
const int EVENT_UNDEF = 0; // Undefined\nconst int EVENT_EXECUTE = 1; // Process start event\nconst int EVENT_CHANGED = 2; // Menu parameter change event\nconst int EVENT_LEAVE = 3; // Menu item focus loss event\nconst int EVENT_TIMER = 4; // Timer fire event\nconst int EVENT_CLOSE = 5; // Menu close event\nconst int EVENT_INIT = 6; // Initialization event\nconst int EVENT_SEL_PREV = 7; // Select event of the previous menu item\nconst int EVENT_SEL_NEXT = 8; // Select event of the next menu item\n
For example, you can use the function associated with the constant EVENT_EXECUTE
to call a script function.
instance MENUITEM_MAIN_INTRO(C_MENU_ITEM_DEF) \n{\n text[0] = \"Play Intro\";\n text[1] = \"Play introduction sequence\";\n // [...]\n onEventAction[EVENT_EXECUTE] = ShowIntro;\n};\n\nfunc int ShowIntro()\n{\n PlayVideo(\"intro.bik\");\n return 1;\n};\n
"},{"location":"zengin/scripts/classes/c_menuitem/#posx","title":"posx","text":"The horizontal position of the top left point of the menu on the screen, measured in virtual coordinates.
Virtual coordinates
Virtual coordinates divide the menu into 8192 parts (0 - 8191
) horizontally and vertically. The position of the menu item is calculated based on these values.
"},{"location":"zengin/scripts/classes/c_menuitem/#posy","title":"posy","text":"The vertical position of the top left point of the menu on the screen, measured in virtual coordinates.
"},{"location":"zengin/scripts/classes/c_menuitem/#dimx","title":"dimx","text":"The width of the menu item in virtual coordinates.
Tip
To automatically determine the width, enter -1
. In this case, the width is calculated based on the text contained in the element.
"},{"location":"zengin/scripts/classes/c_menuitem/#dimy","title":"dimy","text":"The height of the menu item in virtual coordinates.
Tip
To automatically determine the element's height, enter a value of -1
. In this case, the height is calculated taking into account the text contained in the element.
"},{"location":"zengin/scripts/classes/c_menuitem/#sizestartscale","title":"sizeStartScale","text":"Deprecated setting
Size of the menu item at the beginning.
"},{"location":"zengin/scripts/classes/c_menuitem/#flags","title":"flags","text":"Flags of the menu item.
Constants for all flags are described in the file Scripts/System/_intern/Menu.d
.
const int IT_CHROMAKEYED = 1;\nconst int IT_TRANSPARENT = 2;\nconst int IT_SELECTABLE = 4; // Element can be selected\nconst int IT_MOVEABLE = 8;\nconst int IT_TXT_CENTER = 16; // Align text to center\nconst int IT_DISABLED = 32; // Interactive item\nconst int IT_FADE = 64;\nconst int IT_EFFECTS_NEXT = 128; // Flag for influencing an adjacent menu item\nconst int IT_ONLY_OUT_GAME = 256; // Element available only outside the game\nconst int IT_ONLY_IN_GAME = 512; // Element available only in-game\nconst int IT_PERF_OPTION = 1 << 10; // Option responsible for performance\nconst int IT_MULTILINE = 1 << 11; // Multi-line text element\nconst int IT_NEEDS_APPLY = 1 << 12; // Need to apply a settings. Used when changing screen resolution\nconst int IT_NEEDS_RESTART = 1 << 13; // The game need to be restarted\nconst int IT_EXTENDED_MENU = 1 << 14; // Advanced menu flag\n
IT_CHROMAKEYED
Empty flag. Not used.
IT_TRANSPARENT
Empty flag. Not used.
IT_SELECTABLE
Items marked with this flag can be selected.
IT_MOVEABLE
Empty flag. Not used.
Intended use In early engine versions, the initial position of the element could be specified using the startPosX
and startPosY
properties. The element moved from these coordinates to the desired position.
At the beginning of the video below, it can be seen that the elements slides into the screen. That was probably done using this flag and mentioned parameters.
IT_TXT_CENTER
Aligns the text in the element to the center.
IT_DISABLED
The menu item becomes inactive.
instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF)\n{\n text[0] = \"New Game\";\n text[1] = \"Start a new adventure\";\n flags = flags | IT_TXT_CENTER | IT_DISABLED;\n // [...]\n};\n
IT_FADE
Empty flag. Not used.
IT_EFFECTS_NEXT
This flag affects the next neighboring element, i.e., the element specified in the items
list of the C_MENU
class.
instance MENU_OPT_GAME(C_MENU_DEF)\n{\n // [...]\n items[1] = \"MENUITEM_GAME_SUB_TITLES\";\n items[2] = \"MENUITEM_GAME_SUB_TITLES_CHOICE\";\n // [...]\n};\n
In this case, the element affecting (MENUITEM_GAME_SUB_TITLES_CHOICE) is usually made non-selectable.
instance MENUITEM_GAME_SUB_TITLES(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"Subtitles\";\n text[1] = \"Subtitles on/off\";\n flags = flags | IT_EFFECTS_NEXT;\n // [...]\n};\n\ninstance MENUITEM_GAME_SUB_TITLES_CHOICE(C_MENU_ITEM_DEF)\n{\n // [...]\n text[0] = \"no|yes\";\n flags = flags & ~IT_SELECTABLE;\n // [...]\n};\n
This flag is mainly used for options and for managing checkboxes, sliders, and enumerations.
IT_ONLY_OUT_GAME
This flag determines that the menu item is only available before starting the game. Once you start the game, the menu item becomes unavailable.
IT_ONLY_IN_GAME
This flag determines that the menu item is only available in the running game. Until the game is started, the element remains unavailable.
IT_PERF_OPTION
A special flag for options. Settings affecting the game's performance are marked with this flag.
IT_MULTILINE
Flag for multiline text. The text of such elements can be moved to a new line using the newline escape sequence \\n
.
IT_NEEDS_APPLY
Flag indicating the need to apply settings. Used when changing the game resolution.
IT_NEEDS_RESTART
Flag indicating that the game needs to be restarted for the settings to take effect.
IT_EXTENDED_MENU
Flag indicating that this element is part of the \"Extended Menu.\" It is displayed only if the extendedMenu
parameter in the Gothic.ini
file is set to 1
.
"},{"location":"zengin/scripts/classes/c_menuitem/#opendelaytime","title":"openDelayTime","text":"Deprecated setting
Delay before opening a menu item.
"},{"location":"zengin/scripts/classes/c_menuitem/#openduration","title":"openDuration","text":"Deprecated setting
The time the menu item was opened.
"},{"location":"zengin/scripts/classes/c_menuitem/#userfloat","title":"userFloat","text":"Numerical settings of the interface element. Depending on the interface element, the purpose of the property changes. See type.
"},{"location":"zengin/scripts/classes/c_menuitem/#userstring","title":"userString","text":"String settings of the interface element. The purpose of the property changes depending on the interface element. See type`.
"},{"location":"zengin/scripts/classes/c_menuitem/#framesizex","title":"frameSizeX","text":"Indentation of text inside the frame along the X axis. This applies the padding to both sides of the frame. Measured in virtual coordinates from 0 to 4095.
Frames are a special tool designed to work with the log of tasks and quests.
Used for elements of type MENU_ITEM_LISTBOX
.
instance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF)\n{\n backpic = \"NW_Misc_CaveWall_01.tga\";\n type = MENU_ITEM_LISTBOX;\n text[0] = \"Act Missions\";\n // [...]\n userstring[0] = \"CURRENTMISSIONS\";\n framesizex = 2000;\n framesizey = 2000;\n};\n
As a result, we get the following frame (Source: Gothic-Library):
And the width and height of the frame are set, as for all elements, by the dimx and dimy properties.
"},{"location":"zengin/scripts/classes/c_menuitem/#framesizey","title":"frameSizeY","text":"Indentation of text inside the frame along the Y axis. In this case, the indentation is applied at the top and bottom of the frame. Measured in virtual coordinates from 0 to 4095.
See frameSizeX above.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideifoptionsectionset","title":"hideIfOptionSectionSet","text":"The section of the Gothic.ini
file with the option which value of determines the display of this menu item.
This property works together with the hideIfOptionSet
and hideOnValue
properties.
In the example below, the interface element will not be displayed until the useGothic1Controls
parameter in the GAME section is set to 1, i.e., enabled.
instance MENU_ITEM_NEXTMENU(C_MENU_ITEM_DEF)\n{\n text[0] = \"More keys...\";\n text[1] = \"Configure further control keys\";\n // [...]\n hideifoptionsectionset = \"GAME\";\n hideifoptionset = \"useGothic1Controls\";\n hideonvalue = 1;\n};\n
Tip
Gothic.ini
settings can also be changed through the main menu. See onChgSetOption
and onChgSetOptionSection
.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideifoptionset","title":"hideIfOptionSet","text":"The Gothic.ini
file parameter, the value of which determines the display of this menu item.
See hideIfOptionSectionSet.
"},{"location":"zengin/scripts/classes/c_menuitem/#hideonvalue","title":"hideOnValue","text":"The value of the Gothic.ini
file parameter at which this interface element is not displayed.
See hideIfOptionSectionSet.
"},{"location":"zengin/scripts/classes/c_menuitem/#predefined-instances","title":"Predefined instances","text":"There are a lot of predefined class instances in the menu C_MENU_ITEM
performing a strictly defined function. They cannot be renamed, but they can be configured to a certain extent.
Instance Description MENUITEM_LOADSAVE_THUMBPIC Save picture in the Save/Load menu. MENUITEM_LOADSAVE_LEVELNAME_VALUE The name of the level of the selected Save/Load menu item. MENUITEM_LOADSAVE_DATETIME_VALUE The date the selected Save/Load menu item was saved. MENUITEM_LOADSAVE_GAMETIME_VALUE Game time for saving the selected Save/Load menu item. MENUITEM_LOADSAVE_PLAYTIME_VALUE Total play time of the selected Save/Load menu item. MENUITEM_SAVE_SLOT1 - MENUITEM_SAVE_SLOT20 Save menu slots. MENUITEM_LOAD_SLOT1 - MENUITEM_LOAD_SLOT20 Load menu slots. MENU_ITEM_LIST_MISSIONS_ACT Frame with a list of current tasks in the journal. MENU_ITEM_LIST_MISSIONS_FAILED Frame with a list of failed tasks in the log. MENU_ITEM_LIST_MISSIONS_OLD Frame with a list of old tasks in the journal. MENU_ITEM_LIST_LOG Frame of general information in the task log. MENU_ITEM_CONTENT_VIEWER Job log window. MENU_ITEM_DAY Current day in the quest log window. MENU_ITEM_TIME Current time in the task log window. MENU_ITEM_PLAYERGUILD Character's guild in the statistics window. MENU_ITEM_TALENT_0_TITLE - MENU_ITEM_TALENT_16_TITLE The name of the character's talent. Array indexes are used TXT_TALENTS
from the Text.d
file. There may be more elements, depending on the talents realized in the game. MENU_ITEM_TALENT_0_SKILL - MENU_ITEM_TALENT_16_SKILL Character's talent level. Array indexes are used TXT_TALENTS_SKILLS
from the Text.d
file. MENU_ITEM_EXP The character's current experience value in the statistics window. MENU_ITEM_LEVEL Current character level in the statistics window. MENU_ITEM_LEVEL_NEXT The amount of experience required to obtain the next level in the statistics window. MENU_ITEM_LEARN The number of available training points in the statistics window. MENU_ITEM_ATTRIBUTE_1 - MENU_ITEM_ATTRIBUTE_4 Character attributes in the statistics window. MENU_ITEM_ARMOR_1 - MENU_ITEM_ARMOR_4 Character protection in the statistics window."},{"location":"zengin/scripts/classes/c_musicsys_cfg/","title":"C_MUSICSYS_CFG Daedalus class","text":""},{"location":"zengin/scripts/classes/c_musicsys_cfg/#c_musicsys_cfg-daedalus-class","title":"C_MUSICSYS_CFG Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_MusicSys_CFG
defines the global settings for the game's music.
An instance of this class is declared only once.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Music.d
script file.
C_MusicSys_CFG Daedalus class class C_MusicSys_CFG\n{\n var float volume; // Music volume\n var int bitResolution; // Sound quality\n var int globalReverbEnabled; // Enable global reverb\n var int sampleRate; // Frequency\n var int numChannels; // Sound channels\n var int reverbBufferSize; // Reverb buffer size\n};\n
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-members","title":"Class members","text":"Variable Type Description volume float Overall game music volume bitResolution int Sound quality globalReverbEnabled int Enable global reverb sampleRate int Frequency numChannels int Number of sound chanells reverbBufferSize int The size of reverb buffer"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#volume","title":"volume","text":"The overall volume of the background music (soundtrack). From 0.0 to 1.0.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#bitresolution","title":"bitResolution","text":"Sound quality. 8 or 16 bit.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#globalreverbenabled","title":"globalReverbEnabled","text":"Enable global reverb.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#samplerate","title":"sampleRate","text":"Frequency. From 11050 to 44100.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#numchannels","title":"numChannels","text":"Number of sound channels. From 16 to 32.
"},{"location":"zengin/scripts/classes/c_musicsys_cfg/#reverbbuffersize","title":"reverbBufferSize","text":"The size of the reverb buffer.
"},{"location":"zengin/scripts/classes/c_musictheme/","title":"C_MUSICTHEME Daedalus class","text":""},{"location":"zengin/scripts/classes/c_musictheme/#c_musictheme-daedalus-class","title":"C_MUSICTHEME Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
Class C_MusicTheme
describes musical themes.
"},{"location":"zengin/scripts/classes/c_musictheme/#class-definition","title":"Class definition","text":"Class definition as it is defined in Scripts/System/_intern/Music.d
script file.
C_MusicTheme Daedalus class class C_MusicTheme\n{\n var string file; // Sound file in DirectMusic `.sgt` format\n var float vol; // Sound volume\n var int loop; // Enable cycle\n var float reverbMix; // Reverb mixing\n var float reverbTime; // Reverb time\n var int transType; // Type of transition to the next theme\n var int transSubType; // Subtype of transition to the next theme song\n};\n
"},{"location":"zengin/scripts/classes/c_musictheme/#class-members","title":"Class members","text":"Variable Type Description file string Sound file in DirectMusic .sgt
format vol float Sound volume loop int Enable/disable cycle reverbMix float Reverb mixing reverbTime float Reverb time transType int The type of transition to the next theme song transSubType int The subtype of transition to the next theme song"},{"location":"zengin/scripts/classes/c_musictheme/#class-member-overview","title":"Class member overview","text":"Description of the class member variables.
"},{"location":"zengin/scripts/classes/c_musictheme/#file","title":"file","text":"DirectMusic sound in *.sgt format or MIDI file.
"},{"location":"zengin/scripts/classes/c_musictheme/#vol","title":"vol","text":"The volume of the theme song. From 0.0 to 1.0.
"},{"location":"zengin/scripts/classes/c_musictheme/#loop","title":"loop","text":"Enable/disable theme music looping. Disabled = 0. Enabled = 1.
"},{"location":"zengin/scripts/classes/c_musictheme/#reverbmix","title":"reverbMix","text":"Reverb mixing. Measured in decibels.
"},{"location":"zengin/scripts/classes/c_musictheme/#reverbtime","title":"reverbTime","text":"Reverberation time in milliseconds.
"},{"location":"zengin/scripts/classes/c_musictheme/#transtype","title":"transType","text":"The type of transition to the next theme song.
The list of constants for all transitions types is described in the file Scripts/System/_intern/Music.d
const int TRANSITION_TYPE_NONE = 1; // No transition\nconst int TRANSITION_TYPE_GROOVE = 2; // Ripple\nconst int TRANSITION_TYPE_FILL = 3; // Padding\nconst int TRANSITION_TYPE_BREAK = 4; // Break\nconst int TRANSITION_TYPE_INTRO = 5; // Introductory\nconst int TRANSITION_TYPE_END = 6; // End topic\nconst int TRANSITION_TYPE_ENDANDINTRO = 7; // End and start new\n
"},{"location":"zengin/scripts/classes/c_musictheme/#transsubtype","title":"transSubType","text":"The subtype of transition to the next theme song.
The list of constants for all transitions subtypes is described in the file Scripts/System/_intern/Music.d
const INT TRANSITION_SUB_TYPE_IMMEDIATE = 1; // Instant transition\nconst INT TRANSITION_SUB_TYPE_BEAT = 2; // Rhythmic transition\nconst INT TRANSITION_SUB_TYPE_MEASURE = 3; // Gradual transition\n
"},{"location":"zengin/scripts/classes/c_musictheme/#name-features","title":"Name features","text":"The musical themes of the game are played depending on the game situation. By default, the theme with the _STD
(standard) suffix is played. In case of a threat, the _THR
(threat) theme will be played. During the combat the _FGT
(fight) theme plays.
Danger
Make sure that you use proper naming convention for MusicThemes and oCZoneMusic
vobs. The theme with OC_
prefix will play in a zone with name like OLDCAMP_OC
or any other ending with _OC
instance WOO_DAY_STD(C_MUSICTHEME_STANDARD)\n{\n file = \"woo_daystd.sgt\";\n};\n\ninstance WOO_DAY_THR(C_MUSICTHEME_THREAT)\n{\n file = \"woo_daythr.sgt\";\n};\n\ninstance WOO_DAY_FGT(C_MUSICTHEME_FIGHT)\n{\n file = \"woo_dayfgt.sgt\";\n};\n
In addition, the suffix _DAY_
and _NGT_
determines whether the theme should be played on day or night. instance OWD_DAY_FGT(C_MUSICTHEME_FIGHT)\n{\n file = \"owp_dayfgt.sgt\";\n};\n\ninstance OWD_NGT_STD(C_MUSICTHEME_STANDARD)\n{\n file = \"owd_daystd.sgt\";\n};\n
Tip
In G2 the C_MUSICTHEME_STANDARD
, C_MUSICTHEME_THREAT
and C_MUSICTHEME_FIGHT
prototypes are used by default.
"},{"location":"zengin/scripts/classes/c_svm/","title":"C_SVM Daedalus class","text":""},{"location":"zengin/scripts/classes/c_svm/#c_svm-daedalus-class","title":"C_SVM Daedalus class","text":"Acknowledgment
Heavily inspired by the amazing documentation site Gothic library
The C_SVM
class is used to define sound dialogues (smalltalk, reactions) that are defined for every C_NPC.voice.
"},{"location":"zengin/scripts/classes/c_svm/#class-definition","title":"Class definition","text":"C_SVM
class is the only class with variable number of members. The C_SVM
definition in the scripts dictates the content of the class. Every Gothic game has a different number of SVM entries. As an interesting information (more than anything else) we include a table with the numbers of voice lines and voices below.
Game voice lines voices Gothic 1 136 17 Gothic Sequel 110 17 (30 planned) Gothic 2 202 19 Gothic 2 Addon 235 19 Chronicles of Myrtana 1346 73 Returning New Balance 495 19"},{"location":"zengin/scripts/classes/c_svm/#rules","title":"Rules","text":"The number of instances is defined by a constant integer with a specified name read by the engine.
const int SVM_MODULES = 18;\n
Info
The value SVM_MODULES = 18
means 18 SVMs will be parsed by the engine and because the first one, SVM_0
, is empty, the final number of voices is 18 - 1 = 17.
Instances of the C_SVM
class must have the name SVM_XXX
.
instance svm_1(c_svm)\n{\n // ...\n};\n
The first instance svm_0
is always empty, it is used internally by the engine. instance svm_0(c_svm) {};\n
"},{"location":"zengin/scripts/classes/c_svm/#usage-in-the-scripts","title":"Usage in the scripts","text":"While some defined SVMs are used automatically by the engine - the 20 smalltalk lines for example, others are used in the scripts. To instruct the engine to run a specific SVM, external function AI_OutputSVM
is used. In the original scripts it is wrapped in a script function B_Say. To reference the SVM, you use the $
symbol followed by the name of the member variable in the C_SVM
class definition.
// some code\n {\n PrintScreen (\"Not enough skill points!\", -1,-1,\"FONT_OLD_20_WHITE.TGA\",1);\n B_Say (self, other, \"$NOLEARNNOPOINTS\");\n };\n// some code\n
Here the $NOLEARNNOPOINTS
references the var string NoLearnNoPoints
in SVM.D. The voice is then chosen automatically by the engine. class C_SVM\n{\n //...\n\n // Teacher comments\n var string NoLearnNoPoints; // NPC teacher doesn't teach - not enough learning points!\n var string NoLearnOverMax; // NPC teacher doesn't teach - cannot teach above 100 points!\n var string NoLearnYouAlreadyKnow; // You have to know something to become a master!\n var string NoLearnYoureBetter; // You are better than the teacher!\n\n //...\n};\n
"},{"location":"zengin/scripts/extenders/","title":"Daedalus extenders","text":""},{"location":"zengin/scripts/extenders/#daedalus-extenders","title":"Daedalus extenders","text":"The default scripting language Daedalus can be quite limiting. Over the years the community created quite a few extenders to, well, extend the functionality. Before Union came along, the standard to interface with the engine was the script library Ikarus and a collection of packages LeGo built on top of that. Not so recently, an additional script packet was made (and is actively being worked on) AF Script Packet that offers even more functionality and is built on top of Ikarus & LeGo. With the adoption of Union and plugins the Union system can use a new extender emerged called zParserExtender. Other Union plugins can, of course, implement their own external functions. A lot of scripts are also scattered on the Gothic forums, and documentation of some of them can be found in the Standalone section.
"},{"location":"zengin/scripts/extenders/afsp/","title":"AF Script Packet","text":""},{"location":"zengin/scripts/extenders/afsp/#af-script-packet","title":"AF Script Packet","text":"Auronen & Fawkes' Script Packet is a script package built on top of Ikarus and LeGo. It implements many features and there is also a Union version which is in its infancy stage.
Note
AFSP's documentation is lacking (@Auronen: \"My fault\"). The authors will host the documentation on GMC.
Contacts Authors Fawkes & Auronen GitHub AFSP Forum AFSP"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/","title":"Enhanced Information Manager","text":""},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#enhanced-information-manager","title":"Enhanced Information Manager","text":"Warning
This is a quick paste-in of and old version of AFSP's documentation and the information should be taken with a grain of salt. It may not be up-to-date since AFSP is being developed all the time and this is only a demo page.
Enhanced Information Manager allows you to more precisely control the Information Manager (dialogue manager). Change color, font and much more! This package \"scans\" the dialogue string for modifiers and alters the string based on the modifiers you specify.
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#initialization","title":"Initialization","text":"To use this feature you have to:
Add _headers_G[1/2]_EnhancedInfoManager.src
or _headers_G[1/2]_All.src
to your Gothic.src
after Ikarus and LeGo initialization. Call G12_EnhancedInfoManager_Init();
from your INIT_GLOBAL()
function in Startup.d
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-colour","title":"Change colour","text":"Set font color for a dialogue choice.
h@[hex color value]\n
Set font color for highlighted dialogue choice. hs@[hex color value]\n
Exampledescription = \"h@2a85a3 hs@2ea9d1 This dialogue is blue.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-font","title":"Change font","text":"Set font itself for a dialogue choice.
f@[font name]\n
Set font itself for highlighted dialogue choice. fs@[font name]\n
Exampledescription = \"f@font_old_20_white.tga fs@font_old_10_white.tga This dialogue has a different font, when selected.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#change-text-alignment","title":"Change text alignment","text":"Align text left.
al@\n
Align text center. ac@\n
Align text right. ar@\n
Exampledescription = \"al@ This dialogue has LEFT alignment.\";\ndescription = \"ac@ This dialogue has CENTER alignment.\";\ndescription = \"ar@ This dialogue has RIGHT alignment.\";\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#disable-dialogue","title":"Disable dialogue","text":"Player cannot highlight (and select) this dialogue.
d@\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#text-input-field","title":"Text input field","text":"Input field allows you to turn a dialogue choice into an input text field.
a@\n
ExampleINSTANCE DIA_Xardas_Password (C_Info)\n{\n npc = NONE_100_Xardas;\n nr = 1;\n condition = DIA_Xardas_Password_Condition;\n information = DIA_Xardas_Password_Info;\n permanent = FALSE;\n description = \"a@ What is the password to get to the Mages of Water?\";\n};\n\nFUNC INT DIA_Xardas_Password_Condition () {\n return TRUE;\n};\n\nFUNC VOID DIA_Xardas_Password_Info () {\n if (Hlp_StrCmp (InfoManagerAnswer, \"TETRIANDOCH\"))\n {\n PrintScreen (\"Yes that is correct!\", -1, -1, \"font_old_10_white.tga\", 3);\n }\n else\n {\n PrintScreen (\"No that is wrong!\", -1, -1, \"font_old_10_white.tga\", 3);\n };\n};\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#dialogue-numbers","title":"Dialogue numbers","text":"This feature shows a dialogue number next to the dialogue line (visual for Dialogue keyboard controls). To turn this on you just set InfoManagerNumKeysNumbers
variable to true. (in your INIT_GLOBAL()
function).
InfoManagerNumKeysNumbers = TRUE;\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#dialogue-keyboard-controls","title":"Dialogue keyboard controls","text":"Note
This has also been fixed in Union and we noticed a strange behavior with different keyboard layouts.
This feature changes the way number keys affect dialogue selection. The first dialogue is no longer 0 and you highlight the dialogue option by pressing appropriate number.
InfoManagerNumKeysControls = TRUE;\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#spinners","title":"Spinners","text":"This is by far the most flashy feature of EIM as it allows you to use left/right arrow keys on a dialogue option to increase/decease numerical value. This can be used in many ways.
This feature is a bit more complex:
Set up a standard dialogue
Notice
Notice we are using \"dummy\" as a description, since it is going to get updated. If something goes wrong the \"dummy\" string shows up and you can clearly tell something went wrong.
INSTANCE PC_Pan_Cook_Meat (C_Info)\n{\n nr = 1;\n condition = PC_Pan_Cook_Meat_Condition;\n information = PC_Pan_Cook_Meat_Info;\n permanent = TRUE;\n description = \"dummy\"; //Description is updated in PC_Pan_Cook_Meat_Condition\n};\n
Most of the magic takes place in the condition function (apart from the code behind the scenes, of course).
var int selectedMeat; // global variable for this spinner value\n\nFUNC INT PC_Pan_Cook_Meat_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n var string lastSpinnerID;\n\n var int total; total = NPC_HasItems (self, ItFoMuttonRaw);\n\n if (selectedMeat == 0) { selectedMeat = 1; }; //Default initial value\n\n //Check currently selected spinned ID --> is it this one?\n if (Hlp_StrCmp (InfoManagerSpinnerID, \"CookMeat\"))\n {\n //Setup spinner if spinner ID has changed\n if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID))\n {\n //Restore previous value\n InfoManagerSpinnerValue = selectedMeat;\n };\n\n //Page Up/Down quantity\n InfoManagerSpinnerPageSize = 5;\n\n //Min/Max value (Home/End keys)\n InfoManagerSpinnerValueMin = 1;\n InfoManagerSpinnerValueMax = total;\n\n //Update number which is shown in description (in case it was changed by _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT\n selectedMeat = InfoManagerSpinnerValue;\n\n };\n\n lastSpinnerID = InfoManagerSpinnerID; //Remember last active spinner ID\n\n var string newDescription;\n\n //Spinner ID 'CookMeat'\n newDescription = \"s@CookMeat Cook some meat: \";\n\n newDescription = ConcatStrings (newDescription, IntToString (selectedMeat));\n newDescription = ConcatStrings (newDescription, \" / \");\n newDescription = ConcatStrings (newDescription, IntToString (total));\n\n //Update description\n PC_Pan_Cook_Meat.description = newDescription;\n return TRUE;\n };\n\n return FALSE;\n};\n
We can use the spinner value stored in selectedMeat
variable here in the info function to create the meat (or do other stuff with it).
FUNC VOID PC_Pan_Cook_Meat_Info () {\n //If we don't have any meat ... don't cook any :)\n if (!NPC_HasItems (self, ItFoMuttonRaw)) { return; };\n\n //This should not happen - but you never know!\n if (selectedMeat < 1) { return; };\n\n //This should not happen either! but just in case\n if (selectedMeat > (NPC_HasItems (self, ItFoMuttonRaw))) {\n selectedMeat = NPC_HasItems (self, ItFoMuttonRaw);\n };\n\n NPC_RemoveInvItems (self, ItFoMuttonRaw, selectedMeat);\n CreateInvItems (self, ItFoMutton, selectedMeat);\n\n //Reset value for next time\n selectedMeat = 1;\n};\n
"},{"location":"zengin/scripts/extenders/afsp/afsp_eim/#spinners-full-code-example","title":"Spinners: Full code example","text":"Spinner example INSTANCE PC_Pan_Cook_Meat (C_Info)\n{\n nr = 1;\n condition = PC_Pan_Cook_Meat_Condition;\n information = PC_Pan_Cook_Meat_Info;\n permanent = TRUE;\n description = \"dummy\"; //Description is updated in PC_Pan_Cook_Meat_Condition\n};\n\nvar int selectedMeat;\n\nFUNC INT PC_Pan_Cook_Meat_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n var string lastSpinnerID;\n\n var int total; total = NPC_HasItems (self, ItFoMuttonRaw);\n\n if (selectedMeat == 0) { selectedMeat = 1; }; //Default initial value\n\n //Check currently selected spinned ID --> is it this one?\n if (Hlp_StrCmp (InfoManagerSpinnerID, \"CookMeat\"))\n {\n //Setup spinner if spinner ID has changed\n if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID))\n {\n //Restore previous value\n InfoManagerSpinnerValue = selectedMeat;\n };\n\n //Page Up/Down quantity\n InfoManagerSpinnerPageSize = 5;\n\n //Min/Max value (Home/End keys)\n InfoManagerSpinnerValueMin = 1;\n InfoManagerSpinnerValueMax = total;\n\n //Update number which is shown in description (in case it was changed by _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT\n selectedMeat = InfoManagerSpinnerValue;\n };\n\n lastSpinnerID = InfoManagerSpinnerID; //Remember last active spinner ID\n\n var string newDescription;\n\n //Spinner ID 'CookMeat'\n newDescription = \"s@CookMeat Cook some meat: \";\n\n newDescription = ConcatStrings (newDescription, IntToString (selectedMeat));\n newDescription = ConcatStrings (newDescription, \" / \");\n newDescription = ConcatStrings (newDescription, IntToString (total));\n\n //Update description\n PC_Pan_Cook_Meat.description = newDescription;\n return TRUE;\n };\n\n return FALSE;\n};\n\nFUNC VOID PC_Pan_Cook_Meat_Info ()\n{\n //If we don't have any meat ... don't cook any :)\n if (!NPC_HasItems (self, ItFoMuttonRaw)) { return; };\n\n //This should not happen - but you never know!\n if (selectedMeat < 1) { return; };\n\n //This should not happen either! but just in case\n if (selectedMeat > (NPC_HasItems (self, ItFoMuttonRaw)))\n {\n selectedMeat = NPC_HasItems (self, ItFoMuttonRaw);\n };\n\n NPC_RemoveInvItems (self, ItFoMuttonRaw, selectedMeat);\n CreateInvItems (self, ItFoMutton, selectedMeat);\n\n //Reset value for next time\n InfoManagerSpinnerValue = 1;\n};\n\nINSTANCE PC_Pan_Cook_Meat_Exit (C_Info)\n{\n nr = 999;\n condition = PC_Pan_Cook_Meat_Exit_Condition;\n information = PC_Pan_Cook_Meat_Exit_Info;\n permanent = TRUE;\n description = \"End\";\n};\n\nFUNC INT PC_Pan_Cook_Meat_Exit_Condition ()\n{\n if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN)\n {\n return TRUE;\n };\n return FALSE;\n};\n\nFUNC VOID PC_Pan_Cook_Meat_Exit_Info ()\n{\n if (PLAYER_MOBSI_PRODUCTION != MOBSI_DIALOG_NONE)\n {\n PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_NONE;\n hero.aivar[AIV_INVINCIBLE] = FALSE;\n AI_StopProcessInfos (hero);\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/","title":"Ikarus","text":""},{"location":"zengin/scripts/extenders/ikarus/#ikarus","title":"Ikarus","text":"Ikarus is a Daedalus library for Gothic. It exploits the interpreter to allow arbitrary memory access and defines tonne of useful functions for interfacing with the engine.
Contacts Author Sektenspinner & contributors GitHub Ikarus Forum Ikarus Author Note (by Sektenspinner)
This script package is not called Ikarus for nothing:
One can leave the boundaries of Daedalus behind, but may also crash and burn. For instance, reading from invalid addresses won't trigger a zSpy warning but will result in a desktop crash with an Access Violation. This is not a reason to panic but requires a tolerance for frustration (which can be useful for scripters in general).
Of course, such spectacular-looking errors can be fixed, and with focused and systematic work, something sensible can be achieved.
In short: Extra care is needed! A bug that leads to a crash is not something you want in the release version. But if you work cleanly and test extensively, it's not such a big deal.
A good friend in debugging crashes is undoubtedly PrintDebug
. It allows sending messages to zSpy (for example, to narrow down where the crash is occurring). It's worth enabling debug messages by MEM_SetShowDebug
and the text filter (Options -> Textfilter) in zSpy.
Note
Ikarus is hosted on GitHub and the documentation is built in. The translation is planned.
"},{"location":"zengin/scripts/extenders/ikarus/constants/","title":"Ikarus User Constants","text":""},{"location":"zengin/scripts/extenders/ikarus/constants/#ikarus-user-constants","title":"Ikarus User Constants","text":"In the Constants file, you'll find user variables that control various aspects, including the debug output of Ikarus. You can customize these variables to suit your needs.
"},{"location":"zengin/scripts/extenders/ikarus/constants/#mem-helper","title":"MEM-Helper","text":" const string MEM_FARFARAWAY
Waypoint where the Mem-Helper is spawned (default: \"TOT\"
) const string MEM_HELPER_NAME
Name of the Mem-Helper (default: \"MEMHLP\"
) "},{"location":"zengin/scripts/extenders/ikarus/constants/#debug","title":"Debug","text":" const int zERR_ErrorBoxOnlyForFirst
Controls whether only the first error should trigger an error box (default: 1
). const int zERR_StackTraceOnlyForFirst
Determines if stack traces should be displayed only for the first error (default: 0
). "},{"location":"zengin/scripts/extenders/ikarus/constants/#mem_debug","title":"MEM_Debug","text":"The MEM_Debug
function allows you to set up a custom message channel for debugging purposes. You can adjust the following variables to configure this channel:
const string zERR_DEBUG_PREFIX
Specifies a prefix to be added to each debug message (default: \"Debug: \"
). const int zERR_DEBUG_TOSPY
Controls whether MEM_Debug
messages should be sent to zSpy (default: 1
). const int zERR_DEBUG_TYPE
Specifies the message type for MEM_Debug
messages when sent to zSpy (default: zERR_TYPE_INFO
). const int zERR_DEBUG_TOSCREEN
Determines whether MEM_Debug
messages should be printed to the screen (default: 0
). const int zERR_DEBUG_ERRORBOX
Allows you to display an error box for MEM_Debug
messages (default: 0
). "},{"location":"zengin/scripts/extenders/ikarus/constants/#error-message-types","title":"Error message types","text":"const int zERR_TYPE_OK = 0; /* [ungenutzt] */\nconst int zERR_TYPE_INFO = 1; /* MEM_Info */\nconst int zERR_TYPE_WARN = 2; /* MEM_Warn */\nconst int zERR_TYPE_FAULT = 3; /* MEM_Error */\nconst int zERR_TYPE_FATAL = 4; /* [ungenutzt] */\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/","title":"Ikarus examples","text":""},{"location":"zengin/scripts/extenders/ikarus/examples/#ikarus-examples","title":"Ikarus examples","text":"A collection of examples ported from the original Ikarus documentation.
Note
The original Ikarus documentation is a part of the code. You can find it in the GitHub repository.
"},{"location":"zengin/scripts/extenders/ikarus/examples/#open-focused-chest-or-door","title":"Open focused chest or door","text":"func void OpenFocussedChestOrDoor() \n{\n var oCNpc her; her = Hlp_GetNpc(hero);\n\n // No focus vob at all?\n if (!her.focus_vob) \n {\n Print (\"No focus!\");\n return;\n };\n\n // Focus vob not a lockable vob?\n if (!Hlp_Is_oCMobLockable(her.focus_vob))\n {\n Print (\"No chest or door in focus!\");\n return;\n };\n\n var oCMobLockable Lockable;\n Lockable = MEM_PtrToInst (her.focus_vob);\n\n if (Lockable.bitfield & oCMobLockable_bitfield_locked) \n {\n Lockable.bitfield = Lockable.bitfield & ~ oCMobLockable_bitfield_locked;\n Print (ConcatStrings (\"Opened the following vob: \", Lockable._zCObject_objectName));\n } \n else\n {\n Print (ConcatStrings ( Lockable._zCObject_objectName, \"wasn't even complete!\"));\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#print-camera-position","title":"Print camera position","text":"func void PrintCameraPos()\n{\n // Initialize global instances (which only exist once):\n // Initializes MEM_World, MEM_Game, etc. including MEM_Camera\n MEM_InitGlobalInst();\n\n /* The camera object is not a vob (but something abstract), \n do not know where and how there are position data.\n I prefer to work on the camera vob : */\n var zCVob camVob;\n camVob = MEM_PtrToInst (MEM_Camera.connectedVob);\n\n /* Here you have to know how the transformation matrix is structured:\n\n It consists of three vectors, the x, y and z directions of the local coordinate system of the camera vob\n in world coordinates (where z specifies the\n line of sight). These vectors are\n denoted by v1, v2, v3.\n In addition, in the 4th column there is the translation,\n that is, the position of the camera.\n\n v1_x v2_x v3_x x\n v1_y v2_y v3_y y\n v1_z v3_z v3_z z\n 0 0 0 0\n\n The matrix is stored row by row in memory.\n Since we are interested in the last column are the indices\n in the trafoWorld Array 3, 7 and 11 that we need. */\n\n Print (ConcatStrings (\"x: \",IntToString(roundf(camVob.trafoObjToWorld[3]))));\n Print (ConcatStrings (\"y: \",IntToString(roundf(camVob.trafoObjToWorld[7]))));\n Print (ConcatStrings (\"z: \",IntToString(roundf(camVob.trafoObjToWorld[11]))));\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#start-rain","title":"Start rain","text":"func void StartRain()\n{\n // Initialize global instances\n // This also includes Skycontroller\n MEM_InitGlobalInst(); \n\n // start at the beginning of the day (12:00 noon)\n MEM_SkyController.rainFX_timeStartRain = 0; // FLOATNULL constant\n // end at the end of the day (12:00 noon of the next day)\n MEM_SkyController.rainFX_timeStopRain = 1065353216; // FLOATONE constant\n\n /* Note: The start and end times are floating point numbers.\n * 0 stands for the beginning of the day 1 for the end of the day.\n * a day in the game begins at 12:00 p.m.\n * For the structure of the floating point format, google for IEEE-745.*/\n\n /* Result: rain all day! (unless you are in a zone\n * in which it snows, then snow all day) */\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#nested-loop","title":"Nested loop","text":"// Should enumerate all pairs (x,y) with 0 <= x < max_x, 0 <= j < max_y\n\nfunc void printpairs(var int max_x, var int max_y)\n{\n // Initialize labels\n MEM_InitLabels();\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n var int x_loop; x_loop = MEM_StackPos.position;\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n var int y_loop; y_loop = MEM_StackPos.position;\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n // continue y_loop \n MEM_StackPos.position = y_loop;\n };\n x += 1;\n // continue x_loop\n MEM_StackPos.position = x_loop;\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/examples/#calling-a-function-by-their-name","title":"Calling a function by their name","text":"// This example doesn't show why MEM_CallByString * is useful, but how to use the function.\n\nvar zCVob someObject;\nfunc int MyFunction(var int param1, var string str1, var int param2, var string str2)\n{\n Print (ConcatStrings (str1, str2)); //(*)\n return 100 * param1 + param2;\n};\n\nfunc void foo()\n{ \n var int result;\n\n // The following code is in this case equivalent to:\n // result = MyFunction(42, \"Hello\", 23, \"World!\");\n\n // Lay the call arguments on the call stack\n MEM_PushIntParam (42);\n MEM_PushStringParam (\"Hello \");\n MEM_PushIntParam (23);\n MEM_PushStringParam (\"World!\");\n\n MEM_CallByString (\"MYFUNCTION\");\n\n // the function puts the result (of type int in this case) on the stack\n // we pop the int result and save it to a variable\n result = MEM_PopIntResult();\n\n // print the result\n Print (IntToString (result));\n};\n\n/*\n Note: Since symbol indices are continuous and someObject's symbol index \n is simply given by someObject itself, could\n MEM_CallByString(\"MYFUNCTION\"); \n also be replaced here by \n MEM_CallByID(someObject + 1);\n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/","title":"Floats","text":""},{"location":"zengin/scripts/extenders/ikarus/floats/#floats","title":"Floats","text":"This part of ikarus implements support for 32 bit IEEE 754 floats in Daedalus. The script was originally created to edit zFLOAT
and zREAL
variables, but can also be used to arithmetic operations on real float values (not to be confused with Daedalus floats).
"},{"location":"zengin/scripts/extenders/ikarus/floats/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#implementation","title":"Implementation","text":" float.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/floats/#functions","title":"Functions","text":"Danger
Ikarus floats are saved as int but it doesn't mean that you can use arithmetic operators on them. All operations on floats must be done with functions listed below.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#mkf","title":"mkf
","text":"mkf
(make float) Converts the input integer x to a float value.
func int mkf(var int x)\n
Parameters var int x
The input integer Return value
The function returns the float representation of the input integer x.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#truncf","title":"truncf
","text":"truncf
(truncate float) Truncates the decimal part of the input float x.
func int truncf(var int x)\n
Parameters var int x
The input float Return value
The function returns the integer part of the input float x by discarding the decimal part.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#roundf","title":"roundf
","text":"roundf
(round float) Rounds the input float x to the nearest integer value.
func int roundf(var int x)\n
Parameters var int x
The input float Return value
The function returns the nearest integer value to the input float x. If the decimal part is exactly halfway between two integers, the function rounds to the nearest even integer.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#addf","title":"addf
","text":"addf
(add floats) Adds two ikarus floats together.
func int addf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the sum of the input floats x
and y
. (x + y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#subf","title":"subf
","text":"subf
(subtract floats) Subtracts the second float from the first float.
func int subf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the difference between the first float x
and the second float y
. (x - y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#negf","title":"negf
","text":"negf
(negate float) Negates the input float.
func int negf(var int x)\n
Parameters var int x
The input float Return value
The function returns the negation of the input float x
.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#mulf","title":"mulf
","text":"mulf
(multiply floats) Multiplies two ikarus floats.
func int mulf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns the product of multiplying the input floats x and y. (x * y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#divf","title":"divf
","text":"divf
(divide floats) Divides two ikarus floats.
func int divf(var int x, var int y)\n
Parameters var int x
The dividend float var int y
The divisor float Return value
The function returns the quotient of dividing the input float x by y. (x / y)
"},{"location":"zengin/scripts/extenders/ikarus/floats/#invf","title":"invf
","text":"invf
(inverse float) Computes the inverse of the input float.
func int invf(var int x)\n
Parameters var int x
The input float Return value
The function returns the inverse of the x
, calculated as 1/x
.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#gf","title":"gf
","text":"gf
(greater) Checks if the first float is greater than the second float.
func int gf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is greater than y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#gef","title":"gef
","text":"gef
(greater or equal) Checks if the first float is greater than or equal to the second float.
func int gef(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is greater than or equal to y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#lf","title":"lf
","text":"lf
(lower) Checks if the first float is less than the second float.
func int lf(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is less than y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#lef","title":"lef
","text":"lef
(lower or equal) Checks if the first float is less than or equal to the second float.
func int lef(var int x, var int y)\n
Parameters var int x
The first float var int y
The second float Return value
The function returns TRUE
if x
is less than or equal to y
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrf","title":"sqrf
","text":"!!! function \"`sqrf`\"\n(square float) Calculates the square of the float.\n```dae\nfunc int sqrf(var int x)\n```\n**Parameters**\n\n- `#!dae var int x` \n The input float\n\n**Return value**\n\nThe function returns the square of the input float `x`, computed as `x * x`.\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrtf","title":"sqrtf
","text":"!!! function \"`sqrtf`\"\n(square root float) Calculates the square root of the float.\n```dae\nfunc int sqrtf(var int x)\n```\n**Parameters**\n\n- `#!dae var int x` \n The input float\n\n**Return value**\n\nThe function returns the square root of the input float `x`.\n
"},{"location":"zengin/scripts/extenders/ikarus/floats/#sqrtf_approx","title":"sqrtf_approx
","text":"sqrtf_approx
Calculates the approximate square root of a float.
func int sqrtf_approx(var int f)\n
Parameters var int f
The input float Return value
The function returns the approximate square root of the input float as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#absf","title":"absf
","text":"absf
(absolute value) Computes the absolute value of a float.
func int absf(var int x)\n
Parameters var int x
The input float Return value
The function returns the absolute value of the input float x
, which is the value without the negative sign (if present).
"},{"location":"zengin/scripts/extenders/ikarus/floats/#fracf","title":"fracf
","text":"fracf
(fraction) Computes the fraction of two integers p and q.
func int fracf(var int p, var int q)\n
Parameters var int p
Numerator var int q
Denominator Return value
The function returns the fraction of p
divided by q
as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#castfromintf","title":"castFromIntf
","text":"castFromIntf
Converts an ikarus float to a Daedalus float.
func float castFromIntf(var int f)\n
Parameters Return Value
The function returns the value f
as a Daedalus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#casttointf","title":"castToIntf
","text":"castToIntf
Converts a Daedalus float to an ikarus float.
func int castToIntf(var float f)\n
Parameters var float f
Daedalus float Return Value
The function returns the value f
as an ikarus float.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#tostringf","title":"toStringf
","text":"toStringf
Converts a float value to its string representation.
func string toStringf(var int x)\n
Parameters var int x
Input float value Return value
The function returns a string representation of the input float value.
"},{"location":"zengin/scripts/extenders/ikarus/floats/#printf","title":"printf
","text":"printf
(print float) Prints the float on screen using Print()
.
func void printf(var int x)\n
Parameters var int x
The printed float "},{"location":"zengin/scripts/extenders/ikarus/floats/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/floats/#simple-operations","title":"Simple operations","text":"var int float1; float1 = mkf(5); // Create an Ikarus float with value 5\nvar int float2; float2 = mkf(2); // Create an Ikarus float with value 2\n\nvar int addResult; addResluts = addf(float1, float2); // Add float1 and float2\nvar int subResult; subResults = subf(float1, float2); // Subtract float2 from float1\nvar int mulResult; mulRelsults = mulf(float1, float2); // Multiply float1 by float2\nvar int divResult; divResults = divf(float1, float2); // Divide float1 by float2\n\nprintf(addResult); // Output: 7\nprintf(subResult); // Output: 3\nprintf(mulResult); // Output: 10\nprintf(divResult); // Output: 2.5\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/","title":"Ikarus Setup","text":""},{"location":"zengin/scripts/extenders/ikarus/setup/#ikarus-setup","title":"Ikarus Setup","text":""},{"location":"zengin/scripts/extenders/ikarus/setup/#download","title":"Download","text":"First you need to download ikarus from the official github repository. We recommend using the master branch as it contains the latest and most up-to-date version of Ikarus. However, you can also download a specific release if needed.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#file-location","title":"File location","text":"Before unpacking the downloaded archive it's needed to create a dedicated folder in <Gothic-dir>\\_work\\Data\\Scripts\\Content
directory. You can name this folder as you wish; in this guide, we'll refer to it as the \"MOD\" folder. Unpack the downloaded files into this newly created folder. The archiver should create a folder named Ikarus-master
or Ikarus-X.X.X
. For better readability change its name to the much simpler Ikarus
.
Tip
It's a good practice to delete any unused files, so delete files for other gothic version than this you are using.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#parsing","title":"Parsing","text":"Ikarus consists of three main parts, constants, classes and the Ikarus core. It's essential to parse these in a specific order. Additionally, there is a floats package which isn't essential, but it is highly recommended to parse it, especially if you are working with LeGo that depends on it.
The Ikarus Core is identical for both Gothic 1 and 2 and is contained in a single file, Ikarus.d
. However, there are separate files for the constants and classes for each engine, and they must be parsed correctly. Ikarus uses a C_NPC and therefore has to be parsed after the C_NPC class (after the classes.d
file). There are no other dependencies.
Since Ikarus 1.2.1 there is additional .src
file for each game engine, to simplify adding files to Gothic.src
Warning
Following example is for Gothic 2. If you are using Gothic 1 replace the G2
at the end of the file/directory name with G1
.
Gothic.srcGothic.src (Ikarus 1.2.1+) _INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\Ikarus_Const_G2.d\nMOD\\IKARUS\\EngineClasses_G2\\*.d\nMOD\\IKARUS\\Ikarus.d\nMOD\\IKARUS\\float.d\n
_INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G2.SRC\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/#initialization","title":"Initialization","text":"Before you can use Ikarus in your scripts, it must be properly initialized. The initialization process differs between Gothic 1 and Gothic 2.
"},{"location":"zengin/scripts/extenders/ikarus/setup/#mem_initall","title":"MEM_InitAll
","text":"This is main ikarus initialization function, however it consists of some smaller initialization functions.
DeclarationDefinitionList of functions func void MEM_InitAll()\n
func void MEM_InitAll() {\n if (!MEMINT_ReportVersionCheck()) {\n return;\n };\n\n MEM_ReinitParser(); /* depends on nothing */\n MEM_InitLabels(); /* depends in MEM_ReinitParser */\n MEM_InitGlobalInst(); /* depends on MEM_ReinitParser */\n\n /* now I can use MEM_ReplaceFunc, MEM_GetFuncID */\n MEM_GetAddress_Init(); /* depends on MEM_ReinitParser and MEM_InitLabels */\n /* now the nicer operators are available */\n\n MEM_InitStatArrs(); /* depends on MEM_ReinitParser and MEM_InitLabels */\n ASMINT_Init();\n\n MEMINT_ReplaceLoggingFunctions();\n MEMINT_ReplaceSlowFunctions();\n MEM_InitRepeat();\n\n /* takes a wail the first time it is called.\n call it to avoid delay later */\n var int dump; dump = MEM_GetFuncIDByOffset(0);\n};\n
MEM_ReinitParser MEM_InitLabels MEM_InitGlobalInst MEM_GetAddress_Init MEM_InitStatArrs ASMINT_Init MEM_InitRepeat "},{"location":"zengin/scripts/extenders/ikarus/setup/#gothic-1","title":"Gothic 1","text":"To initialize Ikarus in Gothic 1 you must define your own INIT_GLOBAL
function at the top of the Startup.d
file. Then the INIT_GLOBAL
should be called in every INIT_<location>
function (e.g. INIT_SURFACE
,INIT_OLDCAMP
etc.). INIT_SUB_<location>
functions can be skipped in that process.
Then in your INIT_GLOBAL
function you call MEM_InitAll()
initialization function.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n};\n\n// [...]\n\nfunc VOID INIT_SURFACE ()\n{\n Init_Global();\n INIT_SUB_SURFACE ();\n};\n// [...]\n
"},{"location":"zengin/scripts/extenders/ikarus/setup/#gothic-2","title":"Gothic 2","text":"Gothic 2 has its own INIT_GLOBAL
function, so the initialization process is much simpler. All you have to do is to call MEM_InitAll()
in INIT_GLOBAL
function located in the Startup.d
file.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n};\n\n// [...]\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/","title":"Arrays (zCArray)","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#arrays-zcarray","title":"Arrays (zCArray)","text":"Set of function for working with ZenGin's zCArray
data structure.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraycreate","title":"MEM_ArrayCreate
","text":"MEM_ArrayCreate
Creates an empty zCArray
(allocates memory) and returns a pointer to it.
func int MEM_ArrayCreate()\n
Return value The function returns a pointer to the created zCArray
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayfree","title":"MEM_ArrayFree
","text":"MEM_ArrayFree
Frees the memory allocated for a zCArray
and its data.
func void MEM_ArrayFree(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
to be freed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayclear","title":"MEM_ArrayClear
","text":"MEM_ArrayClear
Clears the data of a zCArray
, freeing the memory used by its elements. The array becomes empty.
func void MEM_ArrayClear (var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
to be cleared "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraysize","title":"MEM_ArraySize
","text":"MEM_ArraySize
Returns the size (number of elements) of an array.
func int MEM_ArraySize(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns a number of a zCArray
elements.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraywrite","title":"MEM_ArrayWrite
","text":"MEM_ArrayWrite
Writes a value at a specific position in the zCArray
.
func void MEM_ArrayWrite(var int zCArray_ptr, var int pos, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int pos
Position in the array where the value will be written var int value
Value to be written "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayread","title":"MEM_ArrayRead
","text":"MEM_ArrayRead
Reads the value at a specific position in the zCArray
.
func int MEM_ArrayRead(var int zCArray_ptr, var int pos)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int pos
Position in the array from which the value will be read Return value
The function returns the value at a specific position in the zCArray
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayinsert","title":"MEM_ArrayInsert
","text":"MEM_ArrayInsert
Appends a value to the end of the zCArray
. The array is automatically resized if it is too small.
func void MEM_ArrayInsert (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be inserted "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraypush","title":"MEM_ArrayPush
","text":"MEM_ArrayPush
Alias for MEM_ArrayInsert
, inserts a value at the end of the zCArray
.
func void MEM_ArrayPush (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be inserted "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraypop","title":"MEM_ArrayPop
","text":"MEM_ArrayPop
Removes and returns the last element from the zCArray
.
func int MEM_ArrayPop(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns the element removed from the end of an array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraytop","title":"MEM_ArrayTop
","text":"MEM_ArrayTop
Returns the last element of the zCArray
without removing it.
func int MEM_ArrayTop(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns the last element of an array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayindexof","title":"MEM_ArrayIndexOf
","text":"MEM_ArrayIndexOf
Searches the zCArray
for the first occurrence of a value
and returns its index.
func int MEM_ArrayIndexOf(var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to search for Return value
The function returns the index of a first occurrence of a value
. If not found -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremoveindex","title":"MEM_ArrayRemoveIndex
","text":"MEM_ArrayRemoveIndex
Removes the element at a specific index from the zCArray
.
func void MEM_ArrayRemoveIndex (var int zCArray_ptr, var int index)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int index
Index of the element to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremovevalue","title":"MEM_ArrayRemoveValue
","text":"MEM_ArrayRemoveValue
Removes all occurrences of a value from the zCArray
.
func void MEM_ArrayRemoveValue (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayremovevalueonce","title":"MEM_ArrayRemoveValueOnce
","text":"MEM_ArrayRemoveValueOnce
Removes the first occurrence of a value from the zCArray
. If value is not found, a warning is issued.
func void MEM_ArrayRemoveValueOnce (var int zCArray_ptr, var int value)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
var int value
Value to be removed "},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraysort","title":"MEM_ArraySort
","text":"MEM_ArraySort
Sorts the elements of the zCArray
in ascending order.
func void MEM_ArraySort(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arrayunique","title":"MEM_ArrayUnique
","text":"MEM_ArrayUnique
Removes duplicate elements from the zCArray
.
func void MEM_ArrayUnique(var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
"},{"location":"zengin/scripts/extenders/ikarus/functions/arrays/#mem_arraytostring","title":"MEM_ArrayToString
","text":"MEM_ArrayToString
Converts the zCArray
to a string representation.
func string MEM_ArrayToString (var int zCArray_ptr)\n
Parameters var int zCArray_ptr
Pointer to the zCArray
Return value
The function returns a string representation of a given array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/","title":"Ikarus Machine Code Implementation (ASM)","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#ikarus-machine-code-implementation-asm","title":"Ikarus Machine Code Implementation (ASM)","text":"Machine code refers to a program or program segment written in machine language, which can be directly executed by a processor without further translation steps. The relevant machine language for us is that belonging to the x86 processor architecture. All machine instructions, what they do, and how they are encoded in machine language can be found in the Intel Manuals.
In practice, dealing with (abstract) machine instructions and manually translating them into (concrete) machine code is rarely necessary due to its complexity.
However, machine code can be useful for performing technical tasks that cannot be expressed in Daedalus directly. For example, the CALL package use the ASM function set as a basis.
Note
The functions in this chapter have the ASM_
prefix for Assembly (language). Assembly language is a human-readable language with one-to-one correspondences to machine language. Strictly speaking, the ASM_
prefix is misleading here, as it pertains to machine code rather than assembly language. However, conceptually, the two are closely related.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#opcodes","title":"Opcodes","text":"The code defines several constants that represent different machine code instructions. Each constant is assigned a hexadecimal value and corresponds to a specific machine code instruction. Here is a link to all instructions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#internal-stack","title":"Internal Stack","text":"The code includes an internal stack implementation, allowing the storage of data. The stack is already used at two points:
When calling an engine function, the address of the current run is stored in the internal stack. When nesting the use of the CALL package, a push and pop operation is performed to manage the context. The internal stack is implemented using an array, and the following functions are provided:
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_push","title":"ASMINT_Push
","text":"ASMINT_Push
Pushes the specified data
onto the internal stack.
func void ASMINT_Push(var int data)\n
Parameters var int data
Data pushed onto internal stack "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_pop","title":"ASMINT_Pop
","text":"ASMINT_Pop
Pops and returns the topmost data from the internal stack.
func int ASMINT_Pop()\n
Return value The function returns a data popped form the internal stack.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#functions-core","title":"Functions (Core)","text":"The ASM core functionality provides a framework for assembling machine code instructions and executing them. The following functions are included:
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asmint_init","title":"ASMINT_Init
","text":"ASMINT_Init
Initializes the ASM system by creating an internal stack and finding function addresses.
func void ASMINT_Init()\n
Tip
It's worth noting that ASMINT_Ini
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_open","title":"ASM_Open
","text":"ASM_Open
Changes the size of the memory allocated at the start o the dictation
The memory in which the machine code is stored is allocated at the beginning of the dictation. If this function isn't called a default size (see Constant below) is allocated by ASM
or ASM_Here
function. The 256 bytes is often sufficient for simple applications, but if more memory is required, this function must be called at the beginning of the dictation.
func void ASM_Open(var int space)\n
Parameters var int space
Space allocated for machine code (in bytes) Constant
ASM_StandardStreamLength
constant defines the default space available for an Assembler sequence (in bytes).
const int ASM_StandardStreamLength = 256;\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm","title":"ASM
","text":"ASM
Writes machine code instructions to the stream.
Using this function it is possible to dictate machine code little by little. The data
bytes of the length
(maximum 4!) are appended to the previously dictated part. This creates a program piece by piece that can be executed by the processor.
func void ASM(var int data, var int length)\n
Parameters var int data
The machine code instruction or its part var int length
Length of the data
(max 4 bytes) ASM_1ASM_2ASM_3ASM_4"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_1","title":"ASM_1
","text":"ASM_1
ASM
with length
parameter hardcoded to 1. Writes one byte machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
One byte machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_2","title":"ASM_2
","text":"ASM_2
ASM
with length
parameter hardcoded to 2. Writes two bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Two bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_3","title":"ASM_3
","text":"ASM_3
ASM
with length
parameter hardcoded to 3. Writes three bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Three bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_4","title":"ASM_4
","text":"ASM_4
ASM
with length
parameter hardcoded to 4. Writes four bytes machine code instructions to the stream.
func void ASM_1(var int data) \n
Parameters var int data
Four bytes machine code instruction or its part "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_here","title":"ASM_Here
","text":"ASM_Here
Provides, the address of the cursor, i.e., the address of the location that will be described next by a call to ASM
. It is guaranteed that the location where the code is written is also the location where it will be executed.
func int ASM_Here()\n
Return value
The function returns an address that is the current position in the machine code stream.
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_close","title":"ASM_Close
","text":"ASM_Close
Finalizes the stream by adding a return instruction and returns the starting address of the stream. This pointer can now be passed to at any time and any number of times to execute the machine code.
Warning
The memory area obtained by ASM_Close
must be released manually using MEM_Free
to avoid memory leaks. It is probably sufficient for almost all practical purposes.
func int ASM_Close()\n
Return value The function returns a starting address of the stream (pointer to the stream).
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_run","title":"ASM_Run
","text":"ASM_Run
Executes a machine code (stream) from a pointer.
Note
ASM_Run
can also be used to call engine functions with no parameters and no relevant return value. In this case ptr
would simply have to point to the function to be executed in the code segment.
func void ASM_Run(var int ptr)\n
Parameters var int ptr
Pointer to the executed code (returned form ASM_Close
) "},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#asm_runonce","title":"ASM_RunOnce
","text":"ASM_RunOnce
Executes the code dictated up to that point, similar to how an external function is executed. After that the code is released, and new code can be dictated.
func void ASM_RunOnce()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/asm/#example","title":"Example","text":"The following function sets the NPC passed as slf as the player, as if you had pressed O in Marvin mode with this NPC in focus. This is so short because there is already a function for this exact purpose, it's just not normally accessible from the scripts. It is therefore sufficient to write assembly code that pushes the parameter of the function (the this
pointer) into the appropriate register and then calls the function.
func void SetAsPlayer(var C_NPC slf) { /* Address of the function */\n const int oCNpc__SetAsPlayer = 7612064; //0x7426A0 (Gothic2.exe)\n\n var int slfPtr;\n slfPtr = MEM_InstToPtr (slf);\n\n //mov ecx slfPtr\n ASM_1(ASMINT_OP_movImToECX); /* move a value to ecx */\n ASM_4(slfPtr); /* a value */\n\n //call oCNpc__SetAsPlayer\n ASM_1(ASMINT_OP_call);\n ASM_4(oCNpc__SetAsPlayer - ASM_Here() - 4);\n\n ASM_RunOnce(); /* return will be added automatically */\n};\n
Note
Call targets are specified relative to the instruction that would have been executed after the actual call instruction. Therefore, both ASM_Here() and the subtraction of 4 in the call parameter are necessary.
The above example describes, among other things, CALL__thiscall
function form the CALL Package that can be also used to implement SetAsPlayer
.
func void SetAsPlayer(var C_NPC slf) { \n const int oCNpc__SetAsPlayer = 7612064;\n CALL__thiscall(MEM_InstToPtr(slf), oCNpc__SetAsPlayer);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/","title":"CALL Package","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call-package","title":"CALL Package","text":"This part of Ikarus makes possible to call engine functions directly from scripts.
In order to be able to invoke an engine function, you must know some of its properties. This includes the number and types of parameters, the type of return value, address of function and calling convention.
Knowledge about engine functions can be obtained using tools like IDA, which can analyze and convert GothicMod.exe / Gothic2.exe into a more human-readable format.
Info
In fact, machine code execution (ASM) is part of the CALL package, but due to its complexity, this functionality is discussed in a separate article.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call-modes","title":"Call modes","text":"There are two modes:
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#disposable","title":"Disposable","text":"The simple mode that produces a disposable call that is used only once. All parameters are hardcoded.
func int hero_GetAssessEnemy() {\n const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400\n\n CALL_IntParam(_@(PERC_ASSESSENEMY));\n CALL_PutRetValTo(_@(funcID));\n CALL__thiscall(_@(hero), oCNpc__GetPerceptionFunc);\n\n var int funcID;\n return +funcID;\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#recyclable","title":"Recyclable","text":"The second version produces code that can be used more than once. Instead of the parameters the user specifies the address where the parameters are to be taken from. In addition to executing the code, the user will receive an address that he can use to repeat the call. This is much faster than rebuilding the call from scratch.
func int Npc_GetPercFunc(var C_Npc npc, var int type) {\n const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400\n\n var int npcPtr; npcPtr = _@(npc);\n\n const int call = 0;\n if (CALL_Begin(call)) {\n CALL_IntParam(_@(type));\n CALL_PutRetValTo(_@(funcID));\n CALL__thiscall(_@(npcPtr), oCNpc__GetPerceptionFunc);\n call = CALL_End();\n };\n\n var int funcID;\n return +funcID;\n};\n
Receives a pointer. In case the pointer is non-zero, the code at this position is executed and 0 is returned. In case pointer is zero, the current mode is changed into recyclable mode, this means that the call functions expect instructions to build a recyclable call. This mode will continue until CALL_End()
. This allows code like this:
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#start-and-end","title":"Start and End","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_open","title":"CALL_Open
","text":"CALL_Open
Initializes a Recyclable call mode.
func void CALL_Open()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_begin","title":"CALL_Begin
","text":"CALL_Begin
A practical wrapper for CALL_Open
. Makes a call if it had been already created, initializes it otherwise.
func int CALL_Begin(var int ptr)\n
Parameters var int ptr
Zero if you need to create a new recyclable function to be called (usually, before first use). In this case CALL_Open
is called and CALL_Begin
returns 1
. Return Value
The function returns 1
if the new call has been created, 0
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_close","title":"CALL_Close
","text":"CALL_Close
Finalizes a function call in recyclable mode, restoring the previous execution context.
func int CALL_Close()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_end","title":"CALL_End
","text":"CALL_End
Finalizes a function call, pushes the pointer onto the stack, and runs the associated assembly code (makes an actual call).
func int CALL_End()\n
Return Value
The function returns a pointer that could be used to repeat the call.
Tip
CALL_Close
only finalizes the function call, returning the pointer, while CALL_End
additionally handles pushing the pointer onto the stack and running associated assembly code.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#passing-parameters","title":"Passing parameters","text":"Parameters must be arranged on the machine stack from right to left i.e. from the parameter on the far right to the parameter on the far left. These functions generate machine code that will place parameters on the machine stack when executed.
Note
These functions do not impose any parameters on the Machine stack. Exactly it should say: You create the machine code that will put parameters on the machine stack when it is executed. And it is only carried out in the second step with the announcement of the calling convention.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_intparam","title":"CALL_IntParam
","text":"CALL_IntParam
Passes an integer (int32
) as a parameter to the called function.
func void CALL_IntParam(var int param)\n
Parameters var int param
Address of an integer to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_floatparam","title":"CALL_FloatParam
","text":"CALL_FloatParam
Passes an IEEE 7554 floating-point number (single
/ zREAL
) as a parameter to the called function.
func void CALL_FloatParam(var int param)\n
Parameters var int param
Address of a float to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_ptrparam","title":"CALL_PtrParam
","text":"CALL_PtrParam
Passes a pointer (void*
) as a parameter to the called function.
func void CALL_PtrParam(var int param)\n
Parameters var int param
Pointer to be passed "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_zstringptrparam","title":"CALL_zStringPtrParam
","text":"CALL_zStringPtrParam
Passes a string (zString*
) as a parameter to the called function.
func void CALL_zStringPtrParam(var string param)\n
Parameters var string param
String to be passed Warning
This function only works when writing a disposable call!
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_cstringptrparam","title":"CALL_cStringPtrParam
","text":"CALL_cStringPtrParam
Passes a char array (char **
) as a parameter to the called function.
func void CALL_cStringPtrParam(var string param)\n
Parameters var string param
String to be passed as character array` Warning
This function only works when writing a disposable call!
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_structparam","title":"CALL_StructParam
","text":"CALL_StructParam
Passes a structure (struct) as a parameter to the called function.
func void CALL_StructParam(var int ptr, var int words)\n
Parameters var int param
Pointer to the object var int words
Size of a structure (1 word = 32 bits) Note
CALL_IntParam
, CALL_FloatParam
, and CALL_PtrParam
are functionally identical and are differentiated for code readability.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#the-call","title":"The call","text":"The calling convention determines how the function's parameters are passed. IDA or another disassembler can be used to identify the convention used by a specific engine function.
The announcement of the calling convention, i.e. the call of one of the four functions below is also the time of calling the function. In particular, all parameters must already be specified at this point.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__stdcall","title":"CALL__stdcall
","text":"CALL__stdcall
Calls a function with __stdcall
(Standard Call) calling convention.
func void CALL__stdcall(var int adr)\n
Parameters var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__thiscall","title":"CALL__thiscall
","text":"CALL__thiscall
Calls a function with __thiscall
calling convention. Used with a member functions.
func void CALL__thiscall(var int this, var int adr)\n
Parameters var int this
Pointer to the owner class object passed as a this
parameter var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__cdecl","title":"CALL__cdecl
","text":"CALL__cdecl
Calls a function with __cdecl
calling convention. Used with non-Windows API and non-class functions.
func void CALL__cdecl (var int adr)\n
Parameters var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call__fastcall","title":"CALL__fastcall
","text":"CALL__fastcall
Calls a function with __fastcall
calling convention.
func void CALL__fastcall(var int ecx, var int edx, var int adr)\n
Parameters var int ecx
First parameter of a function var int edx
Second parameter of a function var int adr
Address of a function "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#return-value","title":"Return Value","text":"As soon as the function call has taken place, i.e. after step 2, the return value can be queried. The following functions interpret the return value (usually this is the content of EAX immediately after the call) in the manner suggested in the function name. The result is then returned in a manner usable in Daedalus.
Note
Some return values are not stored in the EAX. In that case the call of the special function RetValIs
is required to get the return value.
Following functions are provided: CALL_RetValIsFloat
, CALL_RetValIszString
, CALL_RetValIsStruct
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_putretvalto","title":"CALL_PutRetValTo
","text":"CALL_PutRetValTo
Simply places the return value to the given address (mostly the address of a daedalus integer). Must be called before The Call function.
func void CALL_PutRetValTo(var int adr)\n
Parameters var int adr
Destination address of the return value "},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasint","title":"CALL_RetValAsInt
","text":"CALL_RetValAsInt
Retrieves an integer returned by the called function.
func int CALL_RetValAsInt()\n
Return value The function returns an integer returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalisfloat","title":"CALL_RetValIsFloat
","text":"CALL_RetValIsFloat
Specifies that the return value is a float. Must be called before The Call function to allow getting the return value with CALL_RetValAsFloat
.
func void CALL_RetValIsFloat()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasfloat","title":"CALL_RetValAsFloat
","text":"CALL_RetValAsFloat
Retrieves a float returned by the called function.
func int CALL_RetValAsFloat()\n
Return value The function returns a float returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasptr","title":"CALL_RetValAsPtr
","text":"CALL_RetValAsPtr
Retrieves a pointer (void*
) returned by the called function.
func int CALL_RetValAsPtr()\n
Return value The function returns a pointer returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalisstruct","title":"CALL_RetValIsStruct
","text":"CALL_RetValIsStruct
Specifies that the return value is a Structure. Must be called before The Call function to allow getting the return value with CALL_RetValAsStructPtr
.
func void CALL_RetValIsStruct(var int size)\n
Parameters var int size
Size of the returned structure in bytes Danger
If the return value is a structure with a size larger than 32 bit, the space for the return value has to be allocated by the caller (this is us).The address to the allocated memory is expected on the stack as an additional parameter (pushed last).
Warning
It is in your responsibility to free the structure memory, when the return value is not needed any more.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalasstructptr","title":"CALL_RetValAsStructPtr
","text":"CALL_RetValAsStructPtr
Retrieves a pointer to the structure returned by the called function and converts it to the instance. Can be used to make an assignment to an instance, for example an assignment to a var zCVob
if the return value is a pointer to a zCVob
.
func MEMINT_HelperClass CALL_RetValAsStructPtr()\n
Return value The function returns an instance returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvaliszstring","title":"CALL_RetValIszString
","text":"CALL_RetValIszString
Specifies that the return value is a zString
(20 bytes structure). Must be called before The Call function to allow getting the return value with CALL_RetValAszStringPtr
and CALL_RetValAszString
.
func string CALL_RetValAszString()\n
Note
CALL_RetValAszStringPtr
and CALL_RetValAszString
are quite different and should not be confused. Using CALL_RetValAszString
frees up memory that may still be needed. In a reverse with CALL_RetValAszStringPtr
memory that is no longer needed is not freed and can cause memory leak.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalaszstringptr","title":"CALL_RetValAszStringPtr
","text":"CALL_RetValAszStringPtr
Retrieves a zString
pointer and converts it to the daedalus string. (don't frees the memory)
func string CALL_RetValAszStringPtr()\n
Return value The function returns a daedalus string form a zString
returned by the previously called engine function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#call_retvalaszstring","title":"CALL_RetValAszString
","text":"CALL_RetValAszString
Retrieves a zString
pointer and converts it to the daedalus string. (frees the memory)
func string CALL_RetValAszString()\n
Return value The function returns a daedalus string form a zString
returned by the previously called engine function.
Function author note A zString
is merely a special case of a structure, with the difference, that it is used as a primitive datatype. Nobody will be willing to use it as a pointer to some memory or an instance in Daedalus. This function copies the contents of the zString
into a daedalus string and frees the zString
afterwards.
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/call/#apply-overlay-disposable","title":"Apply overlay (Disposable)","text":"// .text:0072D2C0:int __thiscall oCNpc::ApplyOverlay(class zSTRING const &)\n\nfunc void example1(){\n const int oCNpc__ApplyOverlay = 7525056; //0x72D2C0 (G2A)\n CALL_zStringPtrParam (\"HUMANS_MILITIA.MDS\");\n CALL__thiscall (MEM_InstToPtr (hero), oCNpc__ApplyOverlay);\n //We are not interested in the return value here.\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#get-time-as-string-disposable","title":"Get time as string (Disposable)","text":"e.g. \"7:30\"
for half past seven in the morning
// .text:00780EC0:class zSTRING __thiscall oCWorldTimer::GetTimeString(void)\n\nfunc void example2(){\n const int oCWorldTimer__GetTimeString = 7868096; //780EC0 (G2A)\n CALL_RetValIszString();\n CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer), oCWorldTimer__GetTimeString );\n PrintDebug (CALL_RetValAszString());\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#get-the-sky-time-disposable","title":"Get the \"sky time\" (Disposable)","text":"Sky time is a floating point value between 0 and 1 that jumps back from 1 to 0 at noon.
// .text:00781240:float __thiscall oCWorldTimer::GetSkyTime(void)\n\nfunc int GetSkyTime() {\n const int oCWorldTimer__GetSkyTime = 7868992; //0x781240\n CALL_RetValIsFloat();\n CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer),\n oCWorldTimer__GetSkyTime);\n\n return CALL_RetValAsFloat();\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/call/#delete-vob-recyclable","title":"Delete Vob (Recyclable)","text":"Call of the oCWorld.RemoveVob
. MEM_DeleteVob
is an ikarus built-in function.
func void MEM_DeleteVob(var int vobPtr) {\n var int world; world = MEM_Game._zCSession_world;\n\n const int call = 0;\n if (CALL_Begin(call)) {\n /* oCWorld.RemoveVob */\n CALL_IntParam(_@(vobPtr));\n CALL__thiscall(_@(world), MEMINT_SwitchG1G2(7171824, 7864512));\n\n call = CALL_End();\n };\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/","title":"Debug","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#debug","title":"Debug","text":"A set of debugging and error-handling functions for mod development with Ikarus.
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_checkversion","title":"MEM_CheckVersion
","text":"MEM_CheckVersion
Checks if the version of Ikarus is the specified version or newer.
func int MEM_CheckVersion(var int base, var int major, var int minor)\n
Parameters var int base
Base version number var int major
Major revision number var int minor
Minor revision number Return value
The function returns TRUE
if the version of Ikarus is the specified version or newer, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_setshowdebug","title":"MEM_SetShowDebug
","text":"MEM_SetShowDebug
Sets the variable that is also toggled by the toggle debug
command. As a result, messages outputted by PrintDebug
are directed to the zSpy
func void MEM_SetShowDebug(var int on)\n
Parameters var int on
Specifies whether to turn on (TRUE
) or off (FALSE
) debug information. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_sendtospy","title":"MEM_SendToSpy
","text":"MEM_SendToSpy
Sends a message to the debugging console.
func void MEM_SendToSpy(var int errorType, var string text)\n
Parameters var int errorType
Type of error (e.g., zERR_TYPE_FAULT
, zERR_TYPE_WARN
, zERR_TYPE_INFO
) var string text
The message to be sent. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_errorbox","title":"MEM_ErrorBox
","text":"MEM_ErrorBox
Displays an error message in a message box.
func void MEM_ErrorBox(var string text)\n
Parameters var string text
The error message to be displayed. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_printstacktrace","title":"MEM_PrintStackTrace
","text":"MEM_PrintStackTrace
Prints the stack trace.
func void MEM_PrintStackTrace()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_error","title":"MEM_Error
","text":"MEM_Error
Handles a fatal error, displaying the error message and printing the stack trace.
func void MEM_Error(var string error)\n
Parameters var string error
The error message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_warn","title":"MEM_Warn
","text":"MEM_Warn
Handles a warning, displaying the warning message and printing the stack trace.
func void MEM_Warn(var string warn)\n
Parameters var string warn
The warning message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_info","title":"MEM_Info
","text":"MEM_Info
Handles an information message, printing it if enabled in the settings.
func void MEM_Info(var string info)\n
Parameters var string info
The information message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_assertfail","title":"MEM_AssertFail
","text":"MEM_AssertFail
Handles an assertion failure, reporting the error message as a fatal error.
func void MEM_AssertFail(var string assertFailText)\n
Parameters var string assertFailText
The assertion failure message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#mem_debug","title":"MEM_Debug
","text":"MEM_Debug
Freely configurable debug channel. See how to setup it in the Constants article.
func void MEM_Debug(var string message)\n
Parameters var string message
The debug message. "},{"location":"zengin/scripts/extenders/ikarus/functions/debug/#memint_switchg1g2","title":"MEMINT_SwitchG1G2
","text":"MEMINT_SwitchG1G2
Switches between values based on the game version. Used mainly to change addresses in multi-platform hooks or function calls.
func int MEMINT_SwitchG1G2(var int g1Val, var int g2Val)\n
Parameters var int g1Val
The value to return if the game version is Gothic 1. var int g2Val
The value to return if the game version is Gothic 2. Return value
The function returns an appropriate value based on the game version.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/","title":"Configuration file access","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#configuration-file-access","title":"Configuration file access","text":"This part of Ikarus gives you access to Gothic.ini
and loaded mod configuration files.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#read-functions","title":"Read functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getcommandline","title":"MEM_GetCommandLine
","text":"MEM_GetCommandLine
Returns the contents of the command line passed to Gothic.
func string MEM_GetCommandLine()\n
Return value The function returns contents of the command line passed to Gothic. This could, for example, look like this:
\"-TIME:7:35 -GAME:TEST_IKARUS.INI -ZREPARSE -ZWINDOW -ZLOG:5,S -DEVMODE -ZMAXFRAMERATE:30\"
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getgothopt","title":"MEM_GetGothOpt
","text":"MEM_GetGothOpt
Searches the Gothic.ini
for an option.
func string MEM_GetGothOpt(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [GAME]
var string optionname
One setting entry like playLogoVideos
Return value
The function returns an option value as a string or empty string if option was not found.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getmodopt","title":"MEM_GetModOpt
","text":"MEM_GetModOpt
Searches the loaded mod ini file for option.
func void MEM_GetModOpt(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [INFO]
var string optionname
One setting entry like Title
Return value
The function returns an option value as a string or empty string if option was not found.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_gothoptsectionexists","title":"MEM_GothOptSectionExists
","text":"MEM_GothOptSectionExists
Checks whether a section exists in Gothic.ini
func int MEM_GothOptSectionExists(var string sectionname)\n
Parameters var string sectionname
Settings section like [GAME]
Return value
The function returns TRUE
if section exists FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_modoptsectionexists","title":"MEM_ModOptSectionExists
","text":"MEM_ModOptSectionExists
Checks whether a section exists in loaded mod ini file
func int MEM_ModOptSectionExists(var string sectionname)\n
Parameters var string sectionname
Settings section like [INFO]
Return value
The function returns TRUE
if section exists FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_gothoptexists","title":"MEM_GothOptExists
","text":"MEM_GothOptExists
Checks whether an option exists in Gothic.ini
func int MEM_GothOptExists(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [GAME]
var string optionname
One setting entry like playLogoVideos
Return value
The function returns TRUE
if option in a section exist FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_modoptexists","title":"MEM_ModOptExists
","text":"MEM_ModOptExists
Checks whether an option exists in loaded mod ini file
func int MEM_ModOptExists(var string sectionname, var string optionname)\n
Parameters var string sectionname
Settings section like [INFO]
var string optionname
One setting entry like Title
Return value
The function returns TRUE
if option in a section exist FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#write-functions","title":"Write functions","text":"Warning
Mod configuration is never saved to disk, therefore no separate functions exist for writing to it.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setgothopt","title":"MEM_SetGothOpt
","text":"MEM_SetGothOpt
The option option
in the section section
is set to the value
. If the section and/or option does not exist, it will be created.
func void MEM_SetGothOpt(var string section, var string option, var string value)\n
Parameters var string section
The section where the option should be located var string option
Option to write/overwrite var string value
Value to set the option to "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_applygothopt","title":"MEM_ApplyGothOpt
","text":"MEM_ApplyGothOpt
Applies the changes and saves the ini to disk
func void MEM_ApplyGothOpt()\n
Tip
If you introduce new options, it is best to follow certain practices. It is a good practice to name your options in a clear manner and place them in a section named the same as your mod. Do not place your mod options into the [GAME]
or [PERFORMANCE]
sections.
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#key-functions","title":"Key functions","text":"The Gothic.ini
contains the assignment of physical keys (e.g. \"W\") to logical keys (e.g. \"keyUp\").
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getkey","title":"MEM_GetKey
","text":"MEM_GetKey
Returns the primary key assigned to logical key.
func int MEM_GetKey(var string name)\n
Parameters var string name
Name of the logical key Return value
The function returns key assigned to logical key
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_getsecondarykey","title":"MEM_GetSecondaryKey
","text":"MEM_GetSecondaryKey
Returns a secondary key assigned to logical key.
func int MEM_GetSecondaryKey(var string name)\n
Parameters var string name
Name of the logical key Return value
The function returns key assigned to logical key
"},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setkeys","title":"MEM_SetKeys
","text":"MEM_SetKeys
Sets keyboard keys of the logical key.
func void MEM_SetKeys(var string name, var int primary, var int secondary)\n
Parameters var string name
Name of the logical key var int primary
Primary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. var int secondary
Secondary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setkey","title":"MEM_SetKey
","text":"MEM_SetKey
Sets the primary keyboard key of the logical key.
func void MEM_SetKey(var string name, var int key)\n
Parameters var string name
Name of the logical key var int key
Primary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/ini_access/#mem_setsecondarykey","title":"MEM_SetSecondaryKey
","text":"MEM_SetSecondaryKey
Sets the secondary keyboard key of the logical key.
func void MEM_SetSecondaryKey(var string name, var int key)\n
Parameters var string name
Name of the logical key var int key
Secondary key to be assigned, can be taken from Ikarus_Const_G1 / Ikarus_Const_G2 file. "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/","title":"Jumps and Loops","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#jumps-and-loops","title":"Jumps and Loops","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#jumps","title":"Jumps","text":"Jumps in Ikarus are implemented by direct manipulation of the stack pointer, achieved with two lines of code. These lines enable the change of the current position within the parser stack, representing machine-level code generated during script compilation. By querying and setting this position, the execution flow can be redirected to a new location in the code.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#initialization","title":"Initialization","text":"To ensure the correct functioning of this jump mechanism, it is crucial to execute the MEM_InitLabels()
function once after loading a saved game. The recommended practice is to integrate this initialization function within INIT_GLOBAL
. It's only after MEM_InitLabels()
has been called that accessing MEM_StackPos.position
becomes valid.
func void MEM_InitLabels()\n
Tip
It's worth noting that MEM_InitLabels
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#usage","title":"Usage","text":" Jump flowchart
flowchart TD\nA(Start) --> B[\"var int label; \\n label = MEM_StackPos.position;\"];\nB --> C{Your code}\nC -->D[\"MEM_StackPos.position = label;\"];\nC --> E(End)\nD --> |Jump| B;
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#notes-and-warnings","title":"Notes and warnings","text":" Validity of Labels Labels become invalid after saving and loading. Consequently, labels should be used immediately, and there is generally no reason to persist them for an extended period.
Caution with Jumping Jumping between different functions without a clear understanding of the code structure can lead to unexpected issues. Similarly, using labels without a thorough comprehension of their purpose may result in undesired consequences. It's crucial to exercise caution, especially when making assignments involving labels.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples","title":"Examples","text":"Simple jump 'loop'Nested jump 'loop' The following code outputs the numbers from 0 to 42:
func void foo() {\n /* Initialization */\n MEM_InitLabels();\n var int count; count = 0;\n\n /* Record the execution position in label. */\n var int label;\n label = MEM_StackPos.position;\n /* <---- label now points here,\n * i.e. to the position AFTER the assignment of label. */\n\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n\n if (count <= 42) {\n /* Replace the execution position,\n * with the \"<-----\" the system then continues */\n MEM_StackPos.position = label;\n };\n\n /* Once 43 is reached, the \u201cloop\u201d is exited. */\n};\n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // Initialize labels\n MEM_InitLabels();\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n var int x_loop; x_loop = MEM_StackPos.position;\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n var int y_loop; y_loop = MEM_StackPos.position;\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n // continue y_loop \n MEM_StackPos.position = y_loop;\n };\n x += 1;\n // continue x_loop\n MEM_StackPos.position = x_loop;\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#label-and-goto","title":"Label and Goto","text":"Besides the normal jumps Ikarus implements MEM_Label
and MEM_Goto
functions. They work similar to the stack manipulation with var int label
but the interface is much more user-friendly and defining new variables is not needed.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#mem_label","title":"MEM_Label
","text":"MEM_Label
Function that works like a label = MEM_StackPos.position;
. You could jump to it with MEM_Goto
.
func void MEM_Label(var int lbl)\n
Parameters var int lbl
Number of the label, used for nested loop or multiple loops within one function "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#mem_goto","title":"MEM_Goto
","text":"MEM_Goto
Function that works like a MEM_StackPos.position = label;
. Executes a jump to a MEM_Label
with specified number.
func void MEM_Goto(var int lbl)\n
Parameters var int lbl
Number of the label, the function will jump to "},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#usage_1","title":"Usage","text":"Usage of Label and Goto is probably self-explanatory, since it is same as in the regular Ikarus Jump. But before using it reading the Notes and warnings of the Jumps is recommended.
Label-Goto loop flowchart
flowchart TD\nA(Start) --> B[\"MEM_Label(0);\"];\nB --> C{Your code}\nC -->D[\"MEM_Goto(0);\"];\nC --> E(End)\nD --> |Jump| B;
Label-Goto loopfunc void LabelGoto_test() {\n var int i; \n MEM_Label(0);\n MEM_Debug(IntToString(i));\n i = i + 1;\n if(i >= 4)\n {\n return;\n };\n MEM_Goto(0);\n};\n\n// Results:\n// Info: 0 Q: Debug: 0\n// Info: 0 Q: Debug: 1\n// Info: 0 Q: Debug: 2\n// Info: 0 Q: Debug: 3\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_1","title":"Examples","text":"Simple Label-Goto 'loop'Nested Label-Goto 'loop' The following code outputs the numbers from 0 to 42:
func void foo() {\n var int count; count = 0;\n\n MEM_Label(0);\n /* <---- label now points here,\n * i.e. to the position AFTER the assignment of label. */\n\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n\n if (count <= 42) {\n // Jump to the MEM_Label\n MEM_Goto(0);\n };\n\n /* Once 43 is reached, the \u201cloop\u201d is exited. */\n};\n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n // while (x < max_x)\n MEM_Label(0);\n if (x < max_x)\n { \n y = 0;\n // while (y < max_y) \n MEM_Label(1);\n if (y < max_y)\n { \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n\n MEM_Goto(1);\n };\n x += 1;\n MEM_Goto(0);\n };\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#while-loop","title":"While loop","text":"Ikarus also implements a while loop. Its syntax isn't as good as the loop from zParserExtender, due to the daedalus limitations, but it works as a normal while loop that can be found in many programming languages.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#syntax","title":"Syntax","text":"The Ikarus while loop consist of three things:
while function That works like a while statement and start of the brace while(var int b){
.
func void while(var int b)\n
end constant That works like an ending brace }
.
const int end = -72;\n
break and continue constant These two constants works like a regular break
and continue
statements in C.
const int break = -42;\nconst int continue = -23;\n
while loopfunc void while_test() {\n var int value; value = 10;\n while(value > 0); //{\n\n if (value == 8)\n {\n continue;\n };\n\n if (value == 2)\n {\n break;\n };\n end; //}\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_2","title":"Examples","text":"Simple while loopNested while loop The following code outputs the numbers from 0 to 42:
func void foo() {\n var int count; count = 0;\n while(count <= 42); //{\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n count += 1;\n end; //}\n\n /* Once 43 is reached, the loop is exited. */\n}; \n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n while(x < max_x); //{\n y = 0;\n while(y < max_y); //{ \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n y += 1;\n end; //}\n x += 1;\n end; //}\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#repeat-loop","title":"Repeat loop","text":"In addition Ikarus implements something called Repeat loop.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#initialization_1","title":"Initialization","text":"To use Repeat loop you must first call MEM_InitRepeat()
function once after loading a saved game. The recommended practice is to integrate this initialization function within INIT_GLOBAL
.
func void MEM_InitRepeat()\n
Tip
It's worth noting that MEM_InitRepeat
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#syntax_1","title":"Syntax","text":"Repeat loop has a syntax very similar to the while loop. It also uses end
constant as an ending brace. break
and continue
statements can be used within it as well. The main difference is the main loop function Repeat
that has following properties:
func void Repeat(var int variable, var int limit)\n
var int variable
A variable that increase with every loop iteration. var int limit
A variable that defines the number of loop iterations. If variable >= limit
the loop is exited. Repeat loop flowchart
flowchart TD\n A(Start) --> B[\"Repeat(i, limit)\"] \n B --> C{i < limit}\n C -->|true| D[Command]\n D --> |i = i + 1| B\n C --> |false| E(End)
Repeat loopfunc void Repeat_test() {\n Repeat(i, 4); var int i; //{\n MEM_Debug(IntToString(i));\n end; //}\n};\n\n// Results:\n// Info: 0 Q: Debug: 0\n// Info: 0 Q: Debug: 1\n// Info: 0 Q: Debug: 2\n// Info: 0 Q: Debug: 3\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/jumps_loops/#examples_3","title":"Examples","text":"Simple Repeat loopNested Repeat loop The following code outputs the numbers from 0 to 42:
func void foo() {\n Repeat(count, 43); var int count; //{\n Print (ConcatStrings (\"COUNT: \", IntToString (count)));\n end; //}\n\n /* Once 43 is reached, the loop is exited. */\n}; \n
The following code should enumerate all pairs (x,y) with 0 <= x < max_x
, 0 <= y < max_y
func void printpairs(var int max_x, var int max_y)\n{\n // PrintDebug should be used, i.e. activate debug output\n MEM_SetShowDebug (1);\n\n var int x; var int y; x = 0;\n\n Repeat(x, max_x); //{\n y = 0;\n Repeat(y, max_y); //{ \n var string out; out = \"(\";\n out = ConcatStrings (out, IntToString (x));\n out = ConcatStrings (out, \", \");\n out = ConcatStrings (out, IntToString (y));\n out = ConcatStrings (out, \")\");\n PrintDebug (out);\n end; //}\n end; //}\n};\n\n/*\n Output of a call printpairs(4,2) would then be: \n 00:36 Info: 5 U: Skript: (0, 0) .... \n 00:36 Info: 5 U: Skript: (0, 1) .... \n 00:36 Info: 5 U: Skript: (1, 0) .... \n 00:36 Info: 5 U: Skript: (1, 1) .... \n 00:36 Info: 5 U: Skript: (2, 0) .... \n 00:36 Info: 5 U: Skript: (2, 1) .... \n 00:36 Info: 5 U: Skript: (3, 0) .... \n 00:36 Info: 5 U: Skript: (3, 1) .... \n*/\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/","title":"Keyboard interaction","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#keyboard-interaction","title":"Keyboard interaction","text":"This part of Ikarus implements function that make interaction with keyboard possible.
Info
Keyboard interaction is also implemented with gameKeyEvents.d
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#functions","title":"Functions","text":"Tip
Different players use different keys for specific actions! However, it is possible to get key assigned to the action from Gothic.ini. See Ini access.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_keypressed","title":"MEM_KeyPressed
","text":"MEM_KeyPressed
Checks if the key is hold right at the moment of function call.
func int MEM_KeyPressed(var int key)\n
Parameters Return value
The function returns TRUE
if the key is hold, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_keystate","title":"MEM_KeyState
","text":"MEM_KeyState
Returns the state of the key
.
func int MEM_KeyState(var int key)\n
Parameters Return value
The function returns actual key state.
Key states
KEY_UP
- The key is not pressed and was not pressed before. (\"not pressed\") KEY_PRESSED
- The key is pressed and was not previously pressed. (\"new pressed\") KEY_HOLD
- The key is pressed and was also pressed before. (\"still pressed\") KEY_RELEASED
- The key is not pressed and was previously pressed. (\"let go\") KEY_PRESSED
or KEY_RELEASED
will be returned if the state of the key has changed since the last query.
KEY_UP
or KEY_HOLD
are returned if the state has not changed.
"},{"location":"zengin/scripts/extenders/ikarus/functions/keyboard/#mem_insertkeyevent","title":"MEM_InsertKeyEvent
","text":"MEM_InsertKeyEvent
Makes the game think that the key was pressed.
func void MEM_InsertKeyEvent(var int key)\n
Parameters var int key
Key to be \"pressed\" "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/","title":"Elementary memory access","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#elementary-memory-access","title":"Elementary memory access","text":"This part of Ikarus makes it possible to read and write memory as different data types - integers, strings, arrays of integers or strings and bytes.
If address <= 0
, an error is thrown. Otherwise, an attempt is made to read or write at this address. If the address falls into invalid range, for example in a code segment, access violation will occur (Gothic crashes). In the case of string operations, it is also necessary that at the specified position a valid zString already exists.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#read-functions","title":"Read functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readint","title":"MEM_ReadInt
","text":"MEM_ReadInt
Reads int from the address
.
func int MEM_ReadInt(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns an integer value if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readstring","title":"MEM_ReadString
","text":"MEM_ReadString
Reads string from the address
.
func string MEM_ReadString(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns string if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readbyte","title":"MEM_ReadByte
","text":"MEM_ReadByte
Reads byte from the address
.
func int MEM_ReadByte(var int address)\n
Parameters var int address
Memory address to read from Return value
The function returns byte value if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readintarray","title":"MEM_ReadIntArray
","text":"MEM_ReadIntArray
Reads int from the array at the arrayAddress
.
func int MEM_ReadIntArray(var int arrayAddress, var int offset)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns integer value from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readstringarray","title":"MEM_ReadStringArray
","text":"Info
MEM_ReadStringArray
has been already moved to the LeGo PermMem package.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_readbytearray","title":"MEM_ReadByteArray
","text":"MEM_ReadByteArray
Reads byte from the array at the arrayAddress
.
func int MEM_ReadByteArray(var int arrayAddress, var int offset)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns byte from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#write-functions","title":"Write functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writeint","title":"MEM_WriteInt
","text":"MEM_WriteInt
Writes int value in the address
.
func void MEM_WriteInt(var int address, var int value)\n
Parameters var int address
Memory address to write into var int value
Integer value to write Example An example of using this function is the following Ikarus function, which turns debugging messages on and off:
func void MEM_SetShowDebug(var int on)\n{\n MEM_WriteInt(showDebugAddress, on);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writestring","title":"MEM_WriteString
","text":"MEM_WriteString
Writes string in the address
.
func void MEM_WriteString(var int address, var string value)\n
Parameters var int address
Memory address to write into var int value
String to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writebyte","title":"MEM_WriteByte
","text":"MEM_WriteByte
Only the byte at address address
is changed here, not a whole four-byte word. That is, the three subsequent bytes remain untouched. If 0 <= val < 256
does not apply in MEM_WriteByte
, a warning is issued and val is trimmed accordingly. In particular, shouldn't be negative numbers are passed.
func void MEM_WriteByte(var int address, var int value)\n
Parameters var int address
Memory address to write into var int value
Byte to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writeintarray","title":"MEM_WriteIntArray
","text":"MEM_WriteIntArray
Writes int value in the array at arrayAddress
.
func void MEM_WriteIntArray(var int arrayAddress, var int offset, var int value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var int value
Integer value to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writestringarray","title":"MEM_WriteStringArray
","text":"MEM_WriteStringArray
Writes string value in the array at arrayAddress
.
func void MEM_WriteStringArray(var int arrayAddress, var int offset, var string value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var string value
String to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_access/#mem_writebytearray","title":"MEM_WriteByteArray
","text":"MEM_WriteByteArray
Writes byte value in the array at arrayAddress
.
func void MEM_WriteByteArray(var int arrayAddress, var int offset, var int value)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) var int value
Byte to write "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/","title":"Memory utility","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#memory-utility","title":"Memory utility","text":"Ikarus utility functions, for memory management and manipulation.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_alloc","title":"MEM_Alloc
","text":"MEM_Alloc
Allocates a specified amount of memory and returns a pointer to the allocated memory area.
Danger
Gothic does not and cannot retain a reference to this memory area or release it, even when destroying the session. Therefore, memory should only be reserved under certain conditions:
It is guaranteed to exist and can be released again with MEM_Free
after loading a save game. Gothic is aware of this memory area and independently releases it. It might be possible to create new objects with this function and permanently integrate them into the object structure of Gothic. However, extreme caution is advised, as object structures cannot be used, and manual handling is required.
This function is well-suited for building small elements like list items and integrating them into existing lists. The memory allocated by this function is always initialized to zero.
func int MEM_Alloc(var int amount)\n
Parameters var int amount
The amount of bytes to allocate Return value
The function returns a pointer to the allocated memory area.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_realloc","title":"MEM_Realloc
","text":"MEM_Realloc
Allocates a memory area of size newsize
and returns a pointer to this memory area. The memory area from location ptr
is released.
If newsize >= oldsize
, the first oldsize
bytes from the old memory area are transferred to the new one. The additional memory is initialized with zero.
If newsize <= oldsize
, all bytes of the new memory area are initialized with the corresponding values of the old memory area.
This function is intended to create an allocated memory area enlarge or reduce. Existing data remains naturally way received.
func int MEM_Realloc(var int ptr, var int oldsize, var int newsize)\n
Parameters var int ptr
The original pointer to the memory block var int oldsize
The size of the original memory block var int newsize
The size of the new memory block Return value
The function returns a pointer to the modified memory area.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_free","title":"MEM_Free
","text":"MEM_Free
Releases an allocated memory area.
Danger
Great caution is advised, especially when attempting to destroy engine objects, as no destructors are called!
Releasing small things such as list elements can be done easily.
func void MEM_Free(var int ptr)\n
Parameters var int ptr
Pointer to the released memory block "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copy","title":"MEM_Copy
","text":"MEM_Copy
Copies a specified number of words from the source address to the destination address.
func void MEM_Copy(var int src, var int dst, var int wordcount)\n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int wordCount
The number of words to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copywords","title":"MEM_CopyWords
","text":"MEM_CopyWords
Alias to MEM_Copy
. Copies a specified number of words from the source address to the destination address.
func void MEM_CopyWords(var int src, var int dst, var int wordcount) \n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int wordCount
The number of words to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_copybytes","title":"MEM_CopyBytes
","text":"MEM_CopyBytes
Copies a specified number of bytes from the source address to the destination address
func void MEM_CopyBytes(var int src, var int dst, var int byteCount)\n
Parameters var int src
The source address to copy from var int dst
The destination address to copy to var int byteCount
The number of bytes to copy "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swap","title":"MEM_Swap
","text":"MEM_Swap
Swaps a specified number of words between the source address and the destination address.
func void MEM_Swap(var int src, var int dst, var int wordCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int wordCount
The number of words to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swapwords","title":"MEM_SwapWords
","text":"MEM_SwapWords
Alias to MEM_Swap
. Swaps a specified number of words between the source address and the destination address.
func void MEM_SwapWords(var int src, var int dst, var int wordCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int wordCount
The number of words to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_swapbytes","title":"MEM_SwapBytes
","text":"MEM_SwapBytes
Swaps a specified number of bytes between the source address and the destination address.
func void MEM_SwapBytes(var int src, var int dst, var int byteCount)\n
Parameters var int src
The source address to swap from var int dst
The destination address to swap to var int byteCount
The number of bytes to swap "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_clear","title":"MEM_Clear
","text":"MEM_Clear
Sets a specified number of bytes in memory to zero.
func void MEM_Clear(var int ptr, var int size)\n
Parameters var int ptr
The memory address to start clearing from var int size
The number of bytes to clear "},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_compare","title":"MEM_Compare
","text":"MEM_Compare
Compares a specified number of words between two memory blocks.
func int MEM_Compare(var int ptr0, var int ptr1, var int wordCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of words to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_comparewords","title":"MEM_CompareWords
","text":"MEM_CompareWords
Alias to MEM_Compare
. Compares a specified number of words between two memory blocks.
func int MEM_CompareWords(var int ptr0, var int ptr1, var int wordCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of words to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/mem_utility/#mem_comparebytes","title":"MEM_CompareBytes
","text":"MEM_CompareBytes
Compares a specified number of bytes between two memory blocks.
func int MEM_CompareBytes(var int ptr1, var int ptr2, var int byteCount)\n
Parameters var int ptr0
The first memory block to compare var int ptr1
The second memory block to compare var int wordCount
The number of bytes to compare Return value
The function returns TRUE
if the memory blocks are equal, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/","title":"Access Menu Objects","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#access-menu-objects","title":"Access Menu Objects","text":"These Ikarus functions are intended to provide and simplify access to menu items (e.g. in the character menu).
Tip
Some menus are generated every time they are used, while others are generated once and then kept. For example, a character menu is only available after it was opened for the first time, after that it is kept in memory. Depending on what you actually want to do, it can make sense to introduce changes in the menu scripts.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#mem_getmenubystring","title":"MEM_GetMenuByString
","text":"MEM_GetMenuByString
func int MEM_GetMenuByString(var string menuName)\n
Parameters
var string menuName
Name of the Gothic menu e.g. MENU_STATUS
Return value
The function returns the address of the menu if a menu with this name exists, null otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/menu_access/#mem_getmenuitembystring","title":"MEM_GetMenuItemByString
","text":"MEM_GetMenuItemByString
func int MEM_GetMenuItemByString(var string menuItemName)\n
Parameters
var string menuItemName
Name of the Gothic menu item e.g. MENU_ITEM_PLAYERGUILD_TITLE
Return value
The function returns the address of the menu item if a menu item with this name exists, null otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/","title":"Ikarus `zCObject` manipulation functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#ikarus-zcobject-manipulation-functions","title":"Ikarus zCObject
manipulation functions","text":"Set of functions for working with zCObject
and its subclasses instances.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#global-instances","title":"Global instances","text":"Ikarus package introduces the following instances:
instance MEM_Game (oCGame);\ninstance MEM_World(oWorld);\ninstance MEM_Timer(zCTimer);\ninstance MEM_WorldTimer(oCWorldTimer);\ninstance MEM_Vobtree(zCTree);\ninstance MEM_InfoMan(oCInfoManager);\ninstance MEM_InformationMan (oCInformationManager);\ninstance MEM_Waynet(zCWaynet);\ninstance MEM_Camera(zCCamera);\ninstance MEM_SkyController(zCSkyController_Outdoor);\ninstance MEM_SpawnManager (oCSpawnManager);\ninstance MEM_GameMananger (CGameManager);\ninstance MEM_GameManager (CGameManager);\ninstance MEM_Parser(zCParser);\n
The classes used here all have one thing in common: there is a maximum of one object of them at the same time (e.g. there is not two worlds or two sky at the same time).
MEM_InitGlobalInst
function sets the offsets of these instances to the corresponding unique object. While it has been called, all of the above instances can be used.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_initglobalinst","title":"MEM_InitGlobalInst
","text":"MEM_InitGlobalInst
Initializes global instances of commonly used objects in the game (is called by the MEM_InitAll
function).
func void MEM_InitGlobalInst()\n
Warning
MEM_InitGlobalInst
must be executed once after loading a savegame. The easiest way is do it is to call this function from INIT_GLOBAL
.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#functions","title":"Functions","text":"About zCClassDef For every class (derived from zCObject
) there is an \"administrative object\" of type zCClassDef
. This encapsulates some useful information about all objects in this class.
class zCClassDef {\n var string className; //zSTRING\n var string baseClassName; //zSTRING\n var string scriptClassName; //zSTRING\n var int baseClassDef; //zCClassDef*\n var int createNewInstance; //zCObject* ( *) (void) \n var int createNewInstanceBackup; //zCObject* ( *) (void)\n var int classFlags; //zDWORD\n var int classSize; //zDWORD\n var int numLivingObjects;\n var int numCtorCalled;\n var int hashTable; //zCObject**\n var int objectList_array; //zCObject**\n var int objectList_numAlloc; //int\n var int objectList_numInArray; //int\n var int bitfield;\n};\n
Full Ikarus definition of this class, with members description can be found in Misc.d
file. The class is same for G1 and G2A engines.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getclassdef","title":"MEM_GetClassDef
","text":"MEM_GetClassDef
Returns a pointer to the zCClassDef
of the object. For more info see the About zCClassDef section above.
Passing these functions a pointer that does not point to a zCObject will most likely result in a crash lead.
func int MEM_GetClassDef(var int objPtr)\n
Parameters var int objPtr
A pointer to the object whose class definition is to be retrieved Return value
The function returns a pointer to the zCClassDef
of the object.
Example This would return a pointer to the zCClassDef
object that belongs to the oCNpc
class.
func int example1\n{\n var int her; her = MEM_InstToPtr(hero);\n return MEM_GetClassDef(her);\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getclassname","title":"MEM_GetClassName
","text":"MEM_GetClassName
This function returns the name of the class to which an object belongs.
func string MEM_GetClassName(var int objPtr)\n
Parameters var int objPtr
A pointer to the object whose class name is to be retrieved Return value
The function returns the objects class name as a string, if the object is invalid an empty string is returned.
Example This would return a name of the oCNpc
class as a string.
func string example2\n{\n var int her; her = MEM_InstToPtr(hero);\n return MEM_GetClassName(her);\n};\n// return: \"oCNpc\"\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_checkinheritance","title":"MEM_CheckInheritance
","text":"MEM_CheckInheritance
Checks if an object is derived from a specific class definition.
func int MEM_CheckInheritance(var int objPtr, var int classDef)\n
Parameters var int objPtr
A pointer to the object to be checked var int classDef
A pointer to the class definition to check against Return value
The function returns TRUE
if the object is derived from the specified class definition, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#hlp_is_","title":"Hlp_Is_*
","text":"Hlp_Is_*
In addition MEM_CheckInheritance
function has some overloads with hardcoded classDef
parameter.
func int Hlp_Is_oCMobFire(var int ptr){};\nfunc int Hlp_Is_zCMover(var int ptr){};\nfunc int Hlp_Is_oCMob(var int ptr){};\nfunc int Hlp_Is_oCMobInter(var int ptr){};\nfunc int Hlp_Is_oCMobLockable(var int ptr){};\nfunc int Hlp_Is_oCMobContainer(var int ptr){};\nfunc int Hlp_Is_oCMobDoor(var int ptr){};\nfunc int Hlp_Is_oCMobBed(var int ptr){};\nfunc int Hlp_Is_oCMobSwitch(var int ptr){};\nfunc int Hlp_Is_oCMobWheel(var int ptr){};\nfunc int Hlp_Is_oCMobLadder(var int ptr){};\nfunc int Hlp_Is_oCNpc(var int ptr){};\nfunc int Hlp_Is_oCItem(var int ptr){};\nfunc int Hlp_Is_zCVobLight(var int ptr){};\n
The usage of these functions is probably obvious, they checks if the given object belongs to class given in the function name.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_insertvob","title":"MEM_InsertVob
","text":"MEM_InsertVob
Inserts a Vob with the visual vis
at the waypoint wp
. If the visual or waypoint does not exist, this is the behaviour this function undefined.
Note
The inserted Vob is even an oCMob
, so it can be given a focus name, for example. But you can treat it like a zCVob
), if you don't need the additional properties.
func int MEM_InsertVob(var string vis, var string wp)\n
Parameters var string vis
Name of the inserted Vob visual (\"FAKESCROLL.3DS\"
, \"FIRE.PFX\"
, \"SNA_BODY.ASC\"
, \"CHESTSMALL_NW_POOR_LOCKED.MDS\"
, \"ADD_PIRATEFLAG.MMS\"
etc.) var string wp
Name of the waypoint to insert Vob on Return value
The function returns a pointer to the created object.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_deletevob","title":"MEM_DeleteVob
","text":"MEM_DeleteVob
Deletes a specific Vob form world.
func void MEM_DeleteVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to a zCVob
object to be deleted "},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_renamevob","title":"MEM_RenameVob
","text":"MEM_RenameVob
Renames the passed Vob to the newName
that is also passed.
The object becomes this first removed from the Vob-hashtable, then unnamed and then again inserted into the Vob-hashtable under a new name.
func void MEM_RenameVob(var int vobPtr, var string newName)\n
Parameters var int vobPtr
Pointer to a zCVob
object to be renamed var string newName
The new Name of the Vob MEM_TriggerVobMEM_UntriggerVob"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_triggervob","title":"MEM_TriggerVob
","text":"MEM_TriggerVob
Sends a trigger message to the Vob.
func void MEM_TriggerVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to a triggered zCVob
Danger
If triggering the Vob has immediate effects (even before MEM_TriggerVob is exited), the name of the Vob is corrupted during this time. It is not advisable to rename, trigger again or destroy the object at this moment, the behavior in such cases is untested.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_untriggervob","title":"MEM_UntriggerVob
","text":"MEM_UntriggerVob
Sends an untrigger message to the Vob.
func void MEM_TriggerVob(var int vobPtr)\n
Parameters var int vobPtr
Pointer to an untriggered zCVob
Danger
If untriggering the Vob has immediate effects (even before MEM_TriggerVob is exited), the name of the Vob is corrupted during this time. It is not advisable to rename, trigger again or destroy the object at this moment, the behavior in such cases is untested.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_searchvobbyname","title":"MEM_SearchVobByName
","text":"MEM_SearchVobByName
Returns the address of a zCVob
named str
if such a Vob exists.
func int MEM_SearchVobByName(var string str)\n
Parameters var string str
Name of searched zCVob
Return value
The function returns a pointer to the zCVob
if the object with the given name exist. 0
is returned otherwise.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_searchallvobsbyname","title":"MEM_SearchAllVobsByName
","text":"MEM_SearchAllVobsByName
Variation of MEM_SearchVobByName
. Creates a zCArray
in which all pointers are to Vobs with the name str
. If no Vob with the name exists, an empty zCArray
is created. A pointer to the created zCArray
is then returned. This can be evaluated, but should be released again with MEM_ArrayFree
before the end of the frame (before the player can load) to avoid memory leaks.
func int MEM_SearchAllVobsByName(var string str)\n
Parameters var string str
Name of searched zCVob
Return value
The function returns a pointer to the created zCArray
, that contains pointers to the all Vobs with the specified name.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getbuffercrc32","title":"MEM_GetBufferCRC32
","text":"MEM_GetBufferCRC32
Calculates the CRC32 hash value from a byte array starting at the address specified by buf
and having a length of buflen
.
func int MEM_GetBufferCRC32(var int buf, var int buflen)\n
Parameters var int buf
Address of a byte array, the hash calculation will begin from
var int buflen
The length of the byte array starting from the address specified by buf
Return value
The function returns the calculated CRC32 hash value.
"},{"location":"zengin/scripts/extenders/ikarus/functions/objects/#mem_getstringhash","title":"MEM_GetStringHash
","text":"MEM_GetStringHash
Calculates the CRC32 hash value for a string.
func int MEM_GetStringHash(var string str)\n
Parameters var string str
A string for which the hash value is to be calculated Return value
The function returns an integer representing the calculated hash value for the input string.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/","title":"`zCParser` related functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#zcparser-related-functions","title":"zCParser
related functions","text":"This Ikarus part provides some useful functions to work with parser, its instances, symbols and stack.
Danger
Remember to always assign an instance to a correct class. If you assign an oCNpc
pointer to oCItem
class you won't be able to read any data from it.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_reinitparser","title":"MEM_ReinitParser
","text":"MEM_ReinitParser
Parser operations are initialized with this function.
func void MEM_ReinitParser()\n
Tip
It's worth noting that MEM_ReinitParser
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#pointers-and-instances","title":"Pointers and instances","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_ptrtoinst","title":"MEM_PtrToInst
","text":"MEM_PtrToInst
Returns an instance pointed to by the pointer. If the pointer is null an error is thrown.
func MEMINT_HelperClass MEM_PtrToInst(var int ptr)\n
Parameters var int ptr
Pointer to return an instance from Shortcut
In addition there is a function _^
with the same signature and functionality as MEM_PtrToInst
. It is used as a shortcut, since the converting pointer to instance is commonly used while working with Ikarus.
func MEMINT_HelperClass _^ (var int ptr)\n
Example Following code
var oCNpc her; her = MEM_PtrToInst(heroPtr);\n
is equivalent to var oCNpc her; her = _^(heroPtr);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_nulltoinst","title":"MEM_NullToInst
","text":"MEM_NullToInst
Returns an instance from a null pointer.
func MEMINT_HelperClass MEM_NullToInst()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_assigninst","title":"MEM_AssignInst
","text":"MEM_AssignInst
Takes an instance from a pointer and assigns it to a given instance. If the pointer is null an error is thrown.
func void MEM_AssignInst(var int inst, var int ptr)\n
Parameters var int ptr
Pointer to assign an instance from var int inst
Instance to which the pointer will be assigned Example Following code
var oCNpc inst;\nMEM_AssignInst (inst, ptr); \n
is equivalent to var oCNpc inst;\ninst = MEM_PtrToInst(ptr);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_assigninstnull","title":"MEM_AssignInstNull
","text":"MEM_AssignInstNull
Assigns null pointer to a given instance.
func void MEM_AssignInstNull(var int inst)\n
Parameters var int inst
Instance to which the null pointer will be assigned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_insttoptr","title":"MEM_InstToPtr
","text":"MEM_InstToPtr
Returns a pointer to given instance.
func int MEM_InstToPtr(var int inst)\n
Parameters var int inst
The instance to which the pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_instgetoffset","title":"MEM_InstGetOffset
","text":"MEM_InstGetOffset
Alias to MEM_InstToPtr
. Returns a pointer to given instance.
func int MEM_InstGetOffset(var int inst)\n
Parameters var int inst
The instance to which the pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_cpyinst","title":"MEM_CpyInst
","text":"MEM_CpyInst
Returns a copy of a given instance
func MEMINT_HelperClass MEM_CpyInst(var int inst)\n
Parameters var int inst
Instance to copy example Following code
selfCopy = MEM_CpyInst (self);\n
is equivalent to selfCopy = MEM_PtrToInst (MEM_InstToPtr (self));\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#call-function","title":"Call function","text":"You don't always know at compile time when you want to call which function. For example, if you want to call the condition function of a mob that the player has in focus, you are at a loss at compile time because you have no idea which mob the player will choose. Ikarus provides a way to call functions based on their name or symbol index. In the example of the mob, the name of the condition function can simply be looked up in the mob.
Note
The functions below also work for externals without any restrictions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#passing-parameters","title":"Passing Parameters","text":"If the function to be called has parameters, these must first be placed on the data stack. The parameters must be pushed in the correct order, from left to right.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushintparam","title":"MEM_PushIntParam
","text":"MEM_PushIntParam
Passes an integer as a parameter to the called function.
func void MEM_PushIntParam (var int param)\n
Parameters var int param
Integer to pass as a function parameter "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushinstparam","title":"MEM_PushInstParam
","text":"MEM_PushInstParam
Passes an instance as a parameter to the called function.
func void MEM_PushInstParam (var int inst)\n
Parameters var int inst
Instance to pass as a function parameter "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_pushstringparam","title":"MEM_PushStringParam
","text":"!!! function \"`MEM_PushStringParam`\"\nPasses a string as a parameter to the called function.\n```dae\nfunc void MEM_PushStringParam (var string str)\n```\n**Parameters**\n\n- `#!dae var string str` \n String to pass as a function parameter\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#the-call","title":"The call","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_call","title":"MEM_Call
","text":"MEM_Call
Calls a function.
func void MEM_Call(var func fnc)\n
Parameters var func fnc
Function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyid","title":"MEM_CallByID
","text":"MEM_CallByID
Calls a function by its ID.
func void MEM_CallByID (var int symbID)\n
Parameters var int symbID
The ID of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyptr","title":"MEM_CallByPtr
","text":"MEM_CallByPtr
Calls a function by its pointer.
func void MEM_CallByPtr(var int ptr)\n
Parameters var int ptr
The pointer of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbyoffset","title":"MEM_CallByOffset
","text":"MEM_CallByOffset
Calls a function by its offset.
func void MEM_CallByOffset(var int offset)\n
Parameters var int offset
The offset of the function to be called "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_callbystring","title":"MEM_CallByString
","text":"MEM_CallByString
Calls a function by its name.
func void MEM_CallByString (var string fnc)\n
Parameters var string fnc
The name of the function IN CAPITAL LETTERS. "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#return-value","title":"Return value","text":"If a function has a return value, it should be fetched from the data stack after it is called, otherwise stack overflows can occur under unfavorable circumstances (aside from that, you may simply want the return value because it contains important information).
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popintresult","title":"MEM_PopIntResult
","text":"MEM_PopIntResult
Retrieves an integer returned by the called function.
func int MEM_PopIntResult()\n
Return value The function returns an integer returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popstringresult","title":"MEM_PopStringResult
","text":"MEM_PopStringResult
Retrieves a daedalus string returned by the called function.
func string MEM_PopStringResult()\n
Return value The function returns a string returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_popinstresult","title":"MEM_PopInstResult
","text":"MEM_PopInstResult
Retrieves an instance returned by the called function.
func MEMINT_HelperClass MEM_PopInstResult()\n
Return value The function returns an instance returned by the previously called script function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#function-stuff","title":"Function stuff","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncid","title":"MEM_GetFuncID
","text":"MEM_GetFuncID
Returns the ID of the given function.
func int MEM_GetFuncID(var func fnc)\n
Parameters var func fnc
The function whose ID is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncptr","title":"MEM_GetFuncPtr
","text":"MEM_GetFuncPtr
Returns the pointer of the given function.
func int MEM_GetFuncPtr(var func fnc)\n
Parameters var func fnc
The function whose pointer is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncoffset","title":"MEM_GetFuncOffset
","text":"MEM_GetFuncOffset
Returns the offset of the given function.
func int MEM_GetFuncOffset(var func fnc)\n
Parameters var func fnc
The function whose offset is returned "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfuncidbyoffset","title":"MEM_GetFuncIDByOffset
","text":"MEM_GetFuncIDByOffset
MEM_GetFuncID
, but with an offset as a parameter.
func int MEM_GetFuncIDByOffset(var int offset)\n
Parameters var int offset
Offset of a function whose ID is returned Return value
The function returns an ID of a function with a given offset.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_replacefunc","title":"MEM_ReplaceFunc
","text":"MEM_ReplaceFunc
Replaces the f1
function with f2
function so if you call the first function, the second function is called.
func void MEM_ReplaceFunc(var func f1, var func f2)\n
Parameters var func f1
Function to replace var func f2
Function called instead of f1
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#parser-stack","title":"Parser stack","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getframeboundary","title":"MEM_GetFrameBoundary
","text":"MEM_GetFrameBoundary
Returns the address/pointer to the boundary of a stack frame (ESP).
func int MEM_GetFrameBoundary()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getcallerstackpos","title":"MEM_GetCallerStackPos
","text":"MEM_GetCallerStackPos
Retrieves the stack position (pop position) of the caller's caller (look at the example for better understanding).
func int MEM_GetCallerStackPos()\n
Return value The function returns an integer representing the stack position of the caller's caller.
Example After calling B()
from within A()
, when MEM_GetCallerStackPos()
is invoked in function B()
, it retrieves the stack position of the caller's caller, which is function A()
in this case. Therefore, the variable adr
will contain the stack position of function A()
.
func void A(){\n B();\n};\n\nfunc void B(){\n int adr; adr = MEM_GetCallerStackPos();\n // Now, 'adr' will contain the stack position of A.\n};\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_setcallerstackpos","title":"MEM_SetCallerStackPos
","text":"MEM_SetCallerStackPos
Sets the stack position (pop position) of the caller's caller.
func void MEM_SetCallerStackPos(var int popPos)\n
Parameters var int popPos
An integer parameter representing the new stack position of the caller's caller "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#get-address","title":"Get address","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getaddress_init","title":"MEM_GetAddress_Init
","text":"MEM_GetAddress_Init
Initializes the MEM_GetIntAddress
, MEM_GetFloatAddress
and MEM_GetStringAddress
functions.
func void MEM_GetAddress_Init()\n
Tip
It's worth noting that MEM_GetAddress_Init
is also invoked by the MEM_InitAll
function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getintaddress","title":"MEM_GetIntAddress
","text":"MEM_GetIntAddress
Returns an address of a given integer.
func int MEM_GetIntAddress(var int i)\n
Parameters var int i
Integer whose address is returned Shortcut
In addition there is a function _@
with the same signature and functionality as MEM_GetIntAddress
.
func int _@(var int i)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getfloataddress","title":"MEM_GetFloatAddress
","text":"MEM_GetFloatAddress
Returns an address of a given daedalus float.
func int MEM_GetFloatAddress(var float f)\n
Parameters var float f
Float whose address is returned Shortcut
In addition there is a function _@f
with the same signature and functionality as MEM_GetFloatAddress
.
func int _@s(var string s)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getstringaddress","title":"MEM_GetStringAddress
","text":"MEM_GetStringAddress
Returns an address of a given string.
func int MEM_GetStringAddress(var string s)\n
Parameters var string s
String whose address is returned Shortcut
In addition there is a function _@s
with the same signature and functionality as MEM_GetStringAddress
.
func int _@s(var string s)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#str_getaddressinit","title":"STR_GetAddressInit
","text":"STR_GetAddressInit
Alias to MEM_GetAddress_Init
, kept for downward compatibility.
func void STR_GetAddressInit()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#str_getaddress","title":"STR_GetAddress
","text":"STR_GetAddress
Function similar to MEM_GetStringAddress
. There is a guarantee, that this function works initialized i.e. invokes MEM_GetAddress_Init
, but the first time may only return an address of a copy of the string.
func int STR_GetAddress(var string str)\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#static-arrays","title":"Static arrays","text":"Accessing static arrays like this below is very tedious in Daedalus.
var int myStaticArray[42];\n
It is not possible to access myStaticArray[i]
with a variable index i, but only with a constant. This changes with the following functions. Danger
Neither function performs any kind of validity check. If the value passed is not an array or offsets are beyond the boundaries of the array passed, the behavior is undefined.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_initstatarrs","title":"MEM_InitStatArrs
","text":"MEM_InitStatArrs
Initializes static arrays read and write functions.
func void MEM_InitStatArrs()\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_writestatarr","title":"MEM_WriteStatArr
","text":"MEM_WriteStatArr
Changes the value at the offset
of a static integer-array.
func void MEM_WriteStatArr (var int array, var int offset, var int value)\n
Parameters var int array
Array which will be edited var int offset
Array index at which value will be edited var int value
The new value "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_readstatarr","title":"MEM_ReadStatArr
","text":"MEM_ReadStatArr
Reads the value at the specific offset of a static integer-array.
func int MEM_ReadStatArr (var int array, var int offset)\n
Parameters var int array
Array to get a value from var int offset
Array index of the value to return Return value
The function returns an integer value from the offset
of a given static array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_writestatstringarr","title":"MEM_WriteStatStringArr
","text":"MEM_WriteStatStringArr
Changes the value at the offset
of a static string-array.
func void MEM_WriteStatStringArr(var string array, var int offset, var string value)\n
Parameters var string array
Array which will be edited var int offset
Array index at which value will be edited var string value
The new value "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_readstatstringarr","title":"MEM_ReadStatStringArr
","text":"MEM_ReadStatStringArr
Reads the value at the specific offset of a static string-array.
func string MEM_ReadStatStringArr(var string array, var int offset)\n
Parameters var string array
Array to get a value from var int offset
Array index of the value to return Return value
The function returns a string form the offset
of a given static array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#parser-symbol","title":"Parser symbol","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_setcurrparsersymb","title":"MEM_SetCurrParserSymb
","text":"MEM_SetCurrParserSymb
Makes currParserSymb
point to the symbol of the specified instance.
func void MEM_SetCurrParserSymb (var int inst)\n
Parameters var int inst
Instance to whose symbol currParserSymb
will be set "},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#currparsersymb","title":"currParserSymb
","text":"currParserSymb
An instance representing current parser symbol.
INSTANCE currParserSymb (zCPar_Symbol);\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_findparsersymbol","title":"MEM_FindParserSymbol
","text":"MEM_FindParserSymbol
Returns the index of the parser symbol with name inst
if such a symbol exists.
func int MEM_FindParserSymbol(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the index of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbolindex","title":"MEM_GetSymbolIndex
","text":"MEM_GetSymbolIndex
Alias to MEM_FindParserSymbol
. Returns the index of the parser symbol with name inst
if such a symbol exists.
func int MEM_GetSymbolIndex(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the index of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and -1
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getparsersymbol","title":"MEM_GetParserSymbol
","text":"MEM_GetParserSymbol
Looks for the parser symbol with the name inst
and returns a pointer to the appropriate zCPar_Symbol
structure.
func int MEM_GetParserSymbol (var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbol","title":"MEM_GetSymbol
","text":"MEM_GetSymbol
Alias to MEM_GetParserSymbol
. Looks for the parser symbol with the name inst
and returns a pointer to the appropriate zCPar_Symbol
structure.
func int MEM_GetSymbol(var string inst)\n
Parameters var string inst
Name of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/parser/#mem_getsymbolbyindex","title":"MEM_GetSymbolByIndex
","text":"MEM_GetSymbolByIndex
MEM_GetParserSymbol
, but with ID (index) as a parameter.
func int MEM_GetSymbolByIndex(var int id)\n
Parameters var string inst
ID (index) of the symbol to be found Return value
The function returns the appropriate zCPar_Symbol
structure of the parser symbol with name inst
if such a symbol exists. If non exists, a warning is issued and 0
is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/","title":"String operations","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/string/#string-operations","title":"String operations","text":"Collection of Ikarus functions to manipulate and format strings.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_getcharat","title":"STR_GetCharAt
","text":"STR_GetCharAt
Returns the ASCII value of a character at a specific position in a string.
func int STR_GetCharAt (var string str, var int pos)\n
Parameters var string str
The input string var int pos
The position of the character Return value
The function returns the ASCII value of the character at the specified position.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_len","title":"STR_Len
","text":"STR_Len
Returns the length of a string.
func int STR_Len (var string str)\n
Parameters var string str
The input string Return value
The function returns the length of the string in characters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_tochar","title":"STR_toChar
","text":"STR_toChar
Converts a string to a pointer to its character array.
func int STR_toChar (var string str)\n
Parameters var string str
The input string Return value
The function returns a pointer to the character array representing the input string str
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_fromchar","title":"STR_FromChar
","text":"STR_FromChar
Converts a character array to a string.
func string STR_FromChar(var int char)\n
Parameters var int char
Pointer to the character array Return value
The function returns a string representation of the character array.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_substr","title":"STR_SubStr
","text":"STR_SubStr
Extracts a substring from a given string.
func string STR_SubStr (var string str, var int start, var int count)\n
Parameters var string str
The input string var int start
The starting position of the substring var int count
The length of the substring Return value
The function returns a substring, if the starting position is invalid an empty string is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_prefix","title":"STR_Prefix
","text":"STR_Prefix
Extracts a prefix of a given string, similar to STR_SubStr
, but with the starting position set to the first character of the string.
func string STR_Prefix (var string str, var int len)\n
Parameters var string str
The input string var int count
The length of the prefix Return value
The function returns a prefix of the input string with the specified length.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_compare","title":"STR_Compare
","text":"STR_Compare
Compares two strings lexicographically and returns a result indicating their relative order.
func int STR_Compare(var string str1, var string str2)\n
Parameters var string str1
The first string to compare var string str2
The second string to compare Return Value
The function returns an integer value representing the result of the comparison:
STR_GREATER
(1): If str1
comes lexicographically after str2
. STR_EQUAL
(0): If str1
is lexicographically equal to str2
. STR_SMALLER
(-1): If str1
comes lexicographically before str2
. Examples The comparison is based on lexicographic order, which is the order of characters as they appear in the ASCII table. Uppercase letters come before lowercase letters.
int result1 = STR_Compare(\"A\", \"B\");\n// The 'result1' variable now contains STR_SMALLER\n\nint result2 = STR_Compare(\"ABC\", \"ABC\");\n// The 'result2' variable now contains STR_EQUAL\n\nint result3 = STR_Compare(\"AA\", \"A\");\n// The 'result3' variable now contains STR_GREATER\n\nint result4 = STR_Compare(\"BA\", \"BB\");\n// The 'result4' variable now contains STR_SMALLER\n\nint result5 = STR_Compare(\"B\", \"a\");\n// The 'result5' variable now contains STR_SMALLER\n\nint result6 = STR_Compare(\"A\", \"\");\n// The 'result6' variable now contains STR_GREATER\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_toint","title":"STR_ToInt
","text":"STR_ToInt
Converts a string to an integer.
func int STR_ToInt (var string str)\n
Parameters var string str
The input string Return Value
The function returns an integer value of the string, if a string is invalid (doesn't contain an integer) zero is returned.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_indexof","title":"STR_IndexOf
","text":"STR_IndexOf
Searches for a substring tok
within a given string and returns the index of the first occurrence of tok
, taking into account upper and lower case letters.
func int STR_IndexOf(var string str, var string tok)\n
Parameters var string str
The string in which to search for tok
. var string tok
The substring to search for within str
. Return Value
The function returns the index at which the first occurrence of tok
begins within str
. If tok
is not found in str
, the function returns -1.
Examples int index1 = STR_IndexOf(\"Hello World!\", \"Hell\");\n// The 'index1' variable now contains 0\n\nint index2 = STR_IndexOf(\"Hello World!\", \"World\");\n// The 'index2' variable now contains 6\n\nint index3 = STR_IndexOf(\"Hello World!\", \"Cake\");\n// The 'index3' variable now contains -1\n\nint index4 = STR_IndexOf(\"Hello World!\", \"\");\n// The 'index4' variable now contains 0\n\nint index5 = STR_IndexOf(\"Hello\", \"Hello World!\");\n// The 'index5' variable now contains -1\n\nint index6 = STR_IndexOf(\"hello Hell!\", \"Hell\");\n// The 'index6' variable now contains 6\n\nint index7 = STR_IndexOf(\"\", \"\");\n// The 'index7' variable now contains 0\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_splitcount","title":"STR_SplitCount
","text":"STR_SplitCount
Counts the number of parts a string splits into when using a specified separator.
func int STR_SplitCount(var string str, var string separator)\n
Parameters var string str
The input string to be split. var string separator
The separator character or string used to split the input string. Return Value
The function returns a number of parts the input string splits into when using the specified separator.
Example string inputStr = \"This is a sentence.\";\nint count = STR_SplitCount(inputStr, \" \");\n// The 'count' variable now contains 4\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_split","title":"STR_Split
","text":"STR_Split
Splits a string into multiple substrings based on a specified separator and returns the substring at a specified offset.
func string STR_Split(var string str, var string separator, var int offset)\n
Parameters
var string str
The input string to be split. var string separator
The separator character or string used to split the input string. var int offset
The index of the substring to be returned after splitting. The index is zero-based. Return Value
The function returns a substring at the specified offset after splitting the input string. If the offset is greater than or equal to the number of parts generated by splitting, an empty string is returned.
Example
func void foo() {\n string inputStr = \"This is a sentence.\";\n string tok1 = STR_Split(inputStr, \" \", 0); // This\n string tok2 = STR_Split(inputStr, \" \", 1); // is\n string tok3 = STR_Split(inputStr, \" \", 2); // a\n string tok4 = STR_Split(inputStr, \" \", 3); // sentence\n};\n
At the end of the function, tok1
contains \"This\", tok2
contains \"is\", tok3
contains \"a\", and tok4
contains \"sentence.\"."},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_upper","title":"STR_Upper
","text":"STR_Upper
Converts a string to uppercase.
func string STR_Upper(var string str)\n
Parameters var string str
The input string Return Value
The function returns a copy of str
with all uppercase letters converted to their corresponding uppercase letters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/string/#str_lower","title":"STR_Lower
","text":"STR_Lower
Converts a string to lowercase.
func string STR_Lower(var string str)\n
Parameters var string str
The input string Return Value
The function returns a copy of str
with all lowercase letters converted to their corresponding uppercase letters.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/","title":"Time and Benchmark","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#time-and-benchmark","title":"Time and Benchmark","text":"Set of functions to time measurement and Benchmark.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#time-functions","title":"Time functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_getsystemtime","title":"MEM_GetSystemTime
","text":"MEM_GetSystemTime
Returns the elapsed time since Gothic started.
func int MEM_GetSystemTime()\n
Return value The function returns the elapsed time since the start of Gothic in milliseconds. This value is used for timing measurements, in the BenchmarkMS
functions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_getperformancecounter","title":"MEM_GetPerformanceCounter
","text":"MEM_GetPerformanceCounter
Call to the WinAPI QueryPerformanceCounter
function.
func int MEM_GetPerformanceCounter()\n
Return value The function returns a value representing the number of elapsed ticks since the system was started. This value is used for timing measurements, in the BenchmarkPC
functions.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#benchmark-functions","title":"Benchmark functions","text":"Tip
For reliable results, avoid measuring a single run of a function; instead, measure the total duration of multiple runs (e.g., 1000). This is crucial, especially for very fast functions, as a single run can distort the measurement. Use _N
benchmark functions to include a parameter specifying the number of runs for function f
.
Choose the parameter n
to ensure meaningful results. If n
executions take less than a millisecond, obtaining a return value in milliseconds has no sense. For very fast functions, the time spent in the benchmark function, not in f
, significantly affects the measurement, falsifying the result. Reliable measurements are achievable only for functions with sufficient slowness.
For reference, here is a timing for some operations (in nanoseconds, i.e., billionths of a second):
- Function call (jumping back and forth): 30ns\n- Elementary calculation (e.g., i = i + 1): 130ns\n- Wld_IsTime: 200ns\n- MEM_ReadInt, MEM_WriteInt: 350ns\n- Hlp_StrCmp(\"Hello\", \"Hello\"): 500ns\n- MEM_InstToPtr: 1400ns\n- (small) Allocate and free memory: 9700ns\n- CALL__stdcall (in empty function): 29000ns\n- MEM_GetParserSymb: 280000ns\n\n- Iteration of the benchmark function: 300ns\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkms","title":"MEM_BenchmarkMS
","text":"MEM_BenchmarkMS
Benchmark of the execution time for a specified function. (Milliseconds)
func int MEM_BenchmarkMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the duration of a function execution in milliseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkmms","title":"MEM_BenchmarkMMS
","text":"MEM_BenchmarkMMS
Benchmark of the execution time for a specified function. (microseconds)
func int MEM_BenchmarkMMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the duration of a function execution in microseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkpc","title":"MEM_BenchmarkPC
","text":"MEM_BenchmarkPC
Benchmark of the execution time for a specified function, using the Performancecounter.
func int MEM_BenchmarkMS(var func f)\n
Parameters var func f
Function to benchmark Return value
The function returns the number of Performancecounter ticks the function needs.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkms_n","title":"MEM_BenchmarkMS_N
","text":"MEM_BenchmarkMS_N
MEM_BenchmarkMS
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkMS_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed duration of multiple (n
) runs of the function in milliseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkmms_n","title":"MEM_BenchmarkMMS_N
","text":"MEM_BenchmarkMMS_N
MEM_BenchmarkMMS
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkMMS_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed duration of multiple (n
) runs of the function in microseconds.
"},{"location":"zengin/scripts/extenders/ikarus/functions/time_benchmark/#mem_benchmarkpc_n","title":"MEM_BenchmarkPC_N
","text":"MEM_BenchmarkPC_N
MEM_BenchmarkPC
, but with the parameter to specify the number of function runs.
func int MEM_BenchmarkPC_N(var func f, var int n)\n
Parameters var func f
Function to benchmark var int n
Number of runs Return value
The function returns a summed number of Performancecounter ticks needed to execute function multiple (n
) times.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/","title":"Windows Utilities","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#windows-utilities","title":"Windows Utilities","text":"This part of Ikarus implements some WinAPI functions that can be used directly from Gothic scripts.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#initialization","title":"Initialization","text":"The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
MEM_InitAll();\n
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#implementation","title":"Implementation","text":" Ikarus.d on GitHub
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#loadlibrary","title":"LoadLibrary
","text":"LoadLibrary
Loads the specified module into the address space of the calling process. Full documentation here.
func int LoadLibrary(var string lpFileName)\n
Parameters var string lpFileName
Name of loaded module Return value
The function returns a handle to the module.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#getprocaddress","title":"GetProcAddress
","text":"GetProcAddress
Retrieves the address from the specified dynamic-link library. Full documentation here.
func int GetProcAddress(var int hModule, var string lpProcName)\n
Parameters var int hModule
A handle to the DLL module that contains the function or variable. Can be obtained using the LoadLibrary
function. var string lpProcName
The function or variable name. Return value The function returns address of the function or variable.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#findkerneldllfunction","title":"FindKernelDllFunction
","text":"FindKernelDllFunction
Uses GetProcAddress
to find function inside the KERNEL32.DLL
file.
func int FindKernelDllFunction(var string name)\n
Parameters var string name
Name of the looked function. Return value
The function returns address of the function.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#virtualprotect","title":"VirtualProtect
","text":"VirtualProtect
Changes the protection on a region of committed pages in the virtual address space of the calling process. Full documentation here.
func int VirtualProtect(var int lpAddress, var int dwSize, var int flNewProtect)\n
Parameters var int lpAddress
The address of the starting page of the region of pages whose access protection attributes are to be changed. var int dwSize
The size of the region whose access protection attributes are to be changed, in bytes. var int flNewProtect
The memory protection option. All options can be found here. Return value
The function returns lpflOldProtectPtr
- a pointer to a variable that receives the previous access protection value.
Author's comment:
I made lpflOldProtectPtr
the return value and ignored the return Value of VirtualProtect.
"},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#memoryprotectionoverride","title":"MemoryProtectionOverride
","text":"MemoryProtectionOverride
Alias to VirtualProtect
but with predefined PAGE_EXECUTE_READWRITE
protection option
func void MemoryProtectionOverride(var int address, var int size)\n
Parameters var int address
The address of the starting page of the region of pages whose access protection attributes are to be changed. var int size
The size of the region whose access protection attributes are to be changed, in bytes. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#mem_messagebox","title":"MEM_MessageBox
","text":"MEM_MessageBox
Calls the WinAPI MessageBox function.
func int MEM_MessageBox(var string txt, var string caption, var int type)\n
Parameters var string txt
Content of the MessageBox. var string caption
Header of MessageBox. var int type
Type of MessageBox. All types listed here. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#mem_infobox","title":"MEM_InfoBox
","text":"MEM_InfoBox
Alias to MEM_MessageBox
with \"Information:\" header and MB_OK | MB_ICONINFORMATION
type.
func void MEM_InfoBox(var string txt)\n
Parameters var string txt
Content of the InfoBox. "},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/ikarus/functions/win_utilities/#sleep","title":"Sleep
","text":"Following function calls the Sleep
function from the KERNEL32.DLL
. A documentation of this function can be found here.
func void Sleep(var int ms) {\n var int adr;\n adr = GetProcAddress(LoadLibrary(\"KERNEL32.DLL\"), \"Sleep\");\n\n CALL_IntParam(ms);\n CALL__stdcall(adr); // 0x007B47E6\n};\n
"},{"location":"zengin/scripts/extenders/lego/","title":"LeGo","text":""},{"location":"zengin/scripts/extenders/lego/#lego","title":"LeGo","text":"LeGo (LehonaGottfried) is a script packet built on top of Ikarus.
Contacts Author Lehona, Gottfried & contributors GitHub LeGo Forum LeGo Note
The code for LeGo is hosted on GitHub and LeGo has its very own documentation page.
"},{"location":"zengin/scripts/extenders/lego/setup/","title":"LeGo Setup","text":""},{"location":"zengin/scripts/extenders/lego/setup/#lego-setup","title":"LeGo Setup","text":"Danger
LeGo depends on Ikarus script packet, if you didn't install it yet check the Ikarus Setup. This guide assumes that you already have Ikarus running.
"},{"location":"zengin/scripts/extenders/lego/setup/#download","title":"Download","text":"First you need to download LeGo from the official github repository. We recommend using the dev
branch as it contains the latest and most up-to-date version of the package. However, you can also download a specific release if needed.
"},{"location":"zengin/scripts/extenders/lego/setup/#file-location","title":"File location","text":"If you followed the Ikarus Setup guide you probably have a \"MOD\" (or any other named) folder inside the <Gothic-dir>\\_work\\Data\\Scripts\\Content
directory. If not create it.
Unpack the downloaded files into this folder. The archiver should create a folder named LeGo-dev
or LeGo-X.X.X
. For better readability change its name to just LeGo
.
Tip
It's a good practice to delete any unused files, so delete files for other gothic version than this you are using.
"},{"location":"zengin/scripts/extenders/lego/setup/#parsing","title":"Parsing","text":"LeGo has a special header files, one for each supported engine version. All you need to do is to include them in Gothic.src
right after the Ikarus files.
Gothic.src (G1)Gothic.src (G2) _INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G1.SRC\nMOD\\LEGO\\HEADER_G1.SRC\n
_INTERN\\CONSTANTS.D\n_INTERN\\CLASSES.D\nMOD\\IKARUS\\IKARUS_G2.SRC\nMOD\\LEGO\\HEADER_G2.SRC\n
"},{"location":"zengin/scripts/extenders/lego/setup/#initialization","title":"Initialization","text":"Before you can use LeGo and its packages, it must be properly initialized.
Warning
Gothic 1 by default doesn't have its own INIT_GLOBAL
function inside Startup.d
file. If you haven't created it yet see how to do it here.
You initialize LeGo by calling the LeGo_Init(var int flags)
function and specifying the flags.
Init AllExclude packagesInit specific packages With LeGo_All
flag you initialize all packages, excluding experimental Buffs and Render.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_All)\n};\n
By the bitwise NOT
operator you can exclude specific packages from LeGo_All
flag.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_All &~ (LeGo_Focusnames | LeGo_Bloodsplats));\n};\n
You could also init specific packages with bitwise OR
.
Startup.dFUNC VOID INIT_GLOBAL()\n{\n // Init Ikarus\n MEM_InitAll ();\n // Init LeGo\n LeGo_Init(LeGo_AI_Function | LeGo_Saves);\n};\n
"},{"location":"zengin/scripts/extenders/lego/userconstants/","title":"User constants","text":""},{"location":"zengin/scripts/extenders/lego/userconstants/#user-constants","title":"User constants","text":"All constants that the user can either use or even change freely are defined in Userconst.d file.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#read-only","title":"Read only","text":"These constants may only be used, not changed.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#anim8","title":"Anim8","text":"These constants are used by Anim8 and Anim8q.
const int A8_Constant
Constant movement speed const int A8_SlowEnd
Evenly decelerated movement const int A8_SlowStart
Evenly accelerated movement const int A8_Wait
Do nothing. The target value is ignored here "},{"location":"zengin/scripts/extenders/lego/userconstants/#buttons","title":"Buttons","text":"The following bit masks can be applied to the status of a button:
const int BUTTON_ACTIVE
The button is active, it reacts to the mouse const int BUTTON_ENTERED
The mouse is \"within\" the button "},{"location":"zengin/scripts/extenders/lego/userconstants/#interface","title":"Interface","text":"Dimensions
const int PS_X
and const int PS_Y
Use with Print_Screen
or Print_ToVirtual
functions const int PS_VMax
Highest possible value of a virtual coordinate Colors
16 basic colors that can be used as zColor
parameters
const int COL_Aqua
const int COL_Black
const int COL_Blue
const int COL_Fuchsia
const int COL_Gray
const int COL_Green
const int COL_Lime
const int COL_Maroon
const int COL_Navy
const int COL_Olive
const int COL_Purple
const int COL_Red
const int COL_Silver
const int COL_Teal
const int COL_White
const int COL_Yellow
"},{"location":"zengin/scripts/extenders/lego/userconstants/#gamestate","title":"Gamestate","text":"Gamestate can assume these values:
const int Gamestate_NewGame
New game started const int Gamestate_Loaded
A game has been loaded const int Gamestate_WorldChange
The world has changed const int Gamestate_Saving
The game is saved "},{"location":"zengin/scripts/extenders/lego/userconstants/#cursor","title":"Cursor","text":"These constants are sent with Cursor_Event
:
const int CUR_LeftClick
The left mouse button was pressed const int CUR_RightClick
The right mouse button was pressed const int CUR_MidClick
The middle mouse button was pressed const int CUR_WheelUp
Mouse wheel up const int CUR_WheelDown
Mouse wheel down "},{"location":"zengin/scripts/extenders/lego/userconstants/#modifiable","title":"Modifiable","text":"These constants are often used by packages and may be changed freely.
"},{"location":"zengin/scripts/extenders/lego/userconstants/#bloodsplats","title":"Bloodsplats","text":" const int BLOODSPLAT_NUM
Maximum number on screen const int BLOODSPLAT_TEX
Highest Texture ID (\"BLOODSPLAT\" + texID + \".TGA\"
) const int BLOODSPLAT_DAM
Texture size damage multiplier (damage * 2
Bloodsplat_Dam
) "},{"location":"zengin/scripts/extenders/lego/userconstants/#cursor_1","title":"Cursor","text":" const string Cursor_Texture
This texture is used to display the cursor (default: \"CURSOR.TGA\") "},{"location":"zengin/scripts/extenders/lego/userconstants/#interface_1","title":"Interface","text":" const string Print_LineSeperator
Text boxes can be printed in multiple lines. This character separates the lines from each other. "},{"location":"zengin/scripts/extenders/lego/userconstants/#prints","title":"PrintS","text":"All position and size information is completely virtual:
const int PF_PrintX
Start position on the X axis const int PF_PrintY
Start position on the Y axis const int PF_TextHeight
Space between individual lines The times are given in ms:
const int PF_FadeInTime
Time to fade in the text const int PF_FadeOutTime
Time to fade out the text const int PF_MoveYTime
Time needed to \"slip down\" const int PF_WaitTime
Time during which the print is fully visible The font can be modified:
const string PF_Font
Default: FONT_OLD_10_WHITE.TGA
"},{"location":"zengin/scripts/extenders/lego/userconstants/#talents","title":"Talents","text":" const int AIV_TALENT
Used AIVar "},{"location":"zengin/scripts/extenders/lego/userconstants/#dialoggestures","title":"Dialoggestures","text":" const string DIAG_Prefix
Animation prefix (\"DG_\") const string DIAG_Suffix
Animation suffix (\"_\") "},{"location":"zengin/scripts/extenders/lego/applications/anim8/","title":"Anim8","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8","title":"Anim8","text":"Info
Dependencies: - Floats Implementation: Anim8.d on GitHub
This package allows int or float values to be \"animated\" over a period of time. It is possible to string several commands together and to set the type of movement. The new version of PrintS
from Interface uses Anim8.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#initialization","title":"Initialization","text":"Initialize with LeGo_Anim8
flag.
LeGo_Init(LeGo_Anim8);\n
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_new","title":"Anim8_New
","text":"Anim8_New
Creates a new Anim8 object that can be filled with commands.
func int Anim8_New(var int initialValue, var int IsFloat)\n
Parameters var int initialValue
The initial value to start animating from. Can be an integer, or an Ikarus float. var int IsFloat
If the initialValue
is an Ikarus float, this parameter must be set to TRUE
. If it is an integer, it must be set to FALSE
. Return value
The function returns handle of the Anim8 object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_newext","title":"Anim8_NewExt
","text":"Anim8_NewExt
Creates a new Anim8 object with advanced options. Extends the Anim8_New
function.
func int Anim8_NewExt(var int value, var func handler, var int data, var int IsFloat)\n
Parameters var int value
The initial value to start animating from. Can be an integer, or an Ikarus float. var func handler
This function is called whenever the object is updated. The signature of the functions depends on the data
value: data != 0
: func void handler(var int data, var int value)
, data == 0
: func void handler(var int value)
. var int data
Optional parameter to send an additional value to the handler
function. If data == 0
, it is ignored. var int IsFloat
If the initialValue
is an Ikarus float, this parameter must be set to TRUE
. If it is an integer, it must be set to FALSE
. Return value
The function returns handle of the Anim8 object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_delete","title":"Anim8_Delete
","text":"Anim8_Delete
Deletes an Anim8 object created with Anim8_New
.
func void Anim8_Delete(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_get","title":"Anim8_Get
","text":"Anim8_Get
Get current value of the object.
func int Anim8_Get(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
Return value
The function returns value of the object.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_set","title":"Anim8_Set
","text":"Anim8_Set
Sets the value of the object.
func void Anim8_Set(var int handle, var int value)\n
Parameters var int handle
Handle returned from Anim8_New
var int value
New value of the object "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_empty","title":"Anim8_Empty
","text":"Anim8_Empty
Indicates whether the object is empty, i.e. has no more commands to process.
func int Anim8_Empty(var int handle)\n
Parameters var int handle
Handle returned from Anim8_New
Return value
The function returns TRUE
if object is empty (has no more commands), FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_removeifempty","title":"Anim8_RemoveIfEmpty
","text":"Anim8_RemoveIfEmpty
If desired, Anim8 can automatically delete an object after it is empty.
func void Anim8_RemoveIfEmpty(var int handle, var int on)\n
Parameters var int handle
Handle returned from Anim8_New
var int on
TRUE
: enable, FALSE
: disable "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_removedataifempty","title":"Anim8_RemoveDataIfEmpty
","text":"Anim8_RemoveDataIfEmpty
With Anim8_NewExt
handler and data can be set. If this function is called with TRUE
, data
is taken as a handle and delete(data)
is called if the object is empty. Works only if Anim8_RemoveIfEmpty
is also activated.
func void Anim8_RemoveDataIfEmpty(var int handle, var int on)\n
Parameters var int handle
Handle returned from Anim8_New
var int on
TRUE
: enable, FALSE
: disable "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_1","title":"Anim8
","text":"Anim8
Packet core. Gives the object a new command to process.
func void Anim8(var int handle, var int target, var int span, var int interpol)\n
Parameters var int handle
Handle returned from Anim8_New
var int target
Target value of this command. When the object's value has reached this value, the command is considered completed and deleted. var int span
Action duration in milliseconds var int interpol
What form of movement is used (See constants for this) "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8q","title":"Anim8q
","text":"Anim8q
As already mentioned above, Anim8 can also process several commands one after the other. While Anim8 completely resets the object and deletes all commands, Anim8q just appends a new command to the list. This will be processed as soon as the previous one is completed.
func void Anim8q(var int handle, var int target, var int span, var int interpol)\n
Parameters var int handle
Handle returned from Anim8_New
var int target
Target value of this command. When the object's value has reached this value, the command is considered completed and another one in the queue will start. var int span
Action duration in milliseconds var int interpol
What form of movement is used (See constants for this) "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#anim8_callonremove","title":"Anim8_CallOnRemove
","text":"Anim8_CallOnRemove
Registers a function to be called when the object is deleted (e.g. by Anim8_RemoveIfEmpty
)
func void Anim8_CallOnRemove(var int handle, var func dfnc)\n
Parameters var int handle
Handle returned from Anim8_New
var func dfnc
This function is called when the object is deleted "},{"location":"zengin/scripts/extenders/lego/applications/anim8/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/anim8/#count-up-to-a-number","title":"Count up to a number","text":"Count from 0 to 10 in 10 seconds. We use the Print_Ext
function from Interface to display the text.
func void Example1()\n{\n // First we create a handle to a text:\n var int MyText; MyText = Print_Ext(20, 20, \"0\", Font_Screen, COL_White, -1);\n\n // After that we create a new, extended Anim8 object.\n // It gets a handler and the handle to the text as data:\n var int MyAnim8; MyAnim8 = Anim8_NewExt(0, MyLoop1, MyText, FALSE); \n // Start value 1, MyLoop1 as handler, MyText as data and no float\n\n // Now the command to count to 10:\n Anim8(MyAnim8, 10, 10000, A8_Constant); // With MyAnim8 to 10 within 10000ms with constant motion.\n\n // So that the text and the Anim8 object are deleted after the process. \n // Now we have to do two more things:\n Anim8_RemoveIfEmpty(MyAnim8, TRUE);\n Anim8_RemoveDataIfEmpty(MyAnim8, TRUE);\n};\n\nfunc void MyLoop1(var int MyText, var int Number)\n{\n var zCViewText t; t = _^(myText);\n\n // Now the text is set to the value of the Anim8 object:\n t.text = IntToString(Number);\n\n // As I said, everything is deleted fully automatically\n};\n
A similar example can be found in the Interface examples."},{"location":"zengin/scripts/extenders/lego/applications/anim8/#moving-zcvob-in-loop","title":"Moving zCVob in loop","text":"Now we make a vob constantly move back and forth, but without a mover. FrameFunctions are used for the loop:
var zCVob MyVob;\nvar int MyVobAni;\n\nfunc void Example2()\n{\n // We use Ikarus to get a pointer to a known VOB:\n MyVob = MEM_PtrToInst(MEM_SearchVobByName(\"MYVOB\"));\n // There must be a vob with the appropriate name in the world for this.\n\n // Since the positions of a vob are floats, this time Anim8 must also use floats:\n MyVobAni = Anim8_New(MyVob.trafoObjToWorld[3], TRUE);\n // The X position of the vob serves as the starting value.\n // We will also move it along this axis.\n\n // Now start a loop that \"nudges\" the vob over and over again:\n FF_Apply(MyVobLoop);\n};\n\nfunc void MyVobLoop()\n{\n // We get the pointer to the VOB again\n MyVob = MEM_PtrToInst(MEM_SearchVobByName(\"MYVOB\"));\n\n // Whenever there are no more commands, we add new ones:\n if(Anim8_Empty(MyVobAni))\n {\n // First move by three meters:\n Anim8(MyVobAni, addf(MyVob.trafoObjToWorld[3], mkf(300)), 1000, A8_SlowEnd);\n // Then wait half a second:\n Anim8q(MyVobAni, 0, 500, A8_Wait);\n // And then back again:\n Anim8q(MyVobAni, MyVob.trafoObjToWorld[3], 1000, A8_SlowEnd);\n // And wait another half a second:\n Anim8q(MyVobAni, 0, 500, A8_Wait);\n // Note the 'q' in the follow-up commands.\n // While Anim8 completely resets the command list, i.e. starts again, Anim8q appends the command to the queue.\n // So you can tinker with a command sequence.\n };\n // Of course, we must set the \"animated\" value to the VOB itself\n MyVob.trafoObjToWorld[3] = Anim8_Get(MyVobAni);\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/","title":"Bars","text":""},{"location":"zengin/scripts/extenders/lego/applications/bars/#bars","title":"Bars","text":"Info
Dependencies: - PermMem - View Implementation: Bars.d on GitHub
This package makes it very easy to add new bars, for e.g. stamina.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#initialization","title":"Initialization","text":"Initialize with LeGo_Bars
flag.
LeGo_Init(LeGo_Bars);\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#functions","title":"Functions","text":"Note
If the GothicBar
prototype is selected as the initial type (GothicBar@
as the constructor), the user's own bars are visually indistinguishable from those used in Gothic.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_create","title":"Bar_Create
","text":"Bar_Create
Creates a new bar from a constructor instance.
func int Bar_Create(var int inst)\n
Parameters
var int inst
Constructor instance of Bar
class Return value
The function returns the address of the new bar, aka the handle.
Examples var int bar; bar = Bar_Create(GothicBar@);
var int bar; bar = Bar_Create(GothicBar@); // Create a new bar\nBar_SetPercent(bar, 50); // And set the value to 50%\n
func void Example_1()\n{\n var int bar; bar = Bar_Create(GothicBar@); // Create a new bar\n Bar_SetPercent(bar, 50); // And set the value to 50%\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_delete","title":"Bar_Delete
","text":"Bar_Delete
Deletes a bar from the screen and from memory.
func void Bar_Delete(var int bar)\n
Parameters
var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setmax","title":"Bar_SetMax
","text":"Bar_SetMax
Changes a bar's maximum value but does not update its bar length (only Bar_SetPercent
, Bar_SetPromille
and Bar_SetValue
)
func void Bar_SetMax(var int bar, var int max)\n
Parameters "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setvalue","title":"Bar_SetValue
","text":"Bar_SetValue
Sets the value of the bar.
func void Bar_SetValue(var int bar, var int val)\n
Parameters var int bar
Handle returned from Bar_Create
var int val
New value of the bar "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setpercent","title":"Bar_SetPercent
","text":"Bar_SetPercent
Sets the value of the bar but as a percentage (0..100).
func void Bar_SetPercent(var int bar, var int perc)\n
Parameters var int bar
Handle returned from Bar_Create
var int perc
New value of the bar in percent "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setpromille","title":"Bar_SetPromille
","text":"Bar_SetPromille
Sets the value of the bar but per mille (0..1000).
func void Bar_SetPromille(var int bar, var int pro)\n
Parameters var int bar
Handle returned from Bar_Create
var int pro
New value of the bar in per mille "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_hide","title":"Bar_Hide
","text":"Bar_Hide
Hides a bar. It will not be deleted.
func void Bar_Hide(var int bar)\n
Parameters var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_show","title":"Bar_Show
","text":"Bar_Show
Displays a bar again after using Bar_Hide
.
func void Bar_Show(var int bar)\n
Parameters var int bar
Handle returned from Bar_Create
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_moveto","title":"Bar_MoveTo
","text":"Bar_MoveTo
Move the bar to virtual position.
func void Bar_MoveTo(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New horizontal position in virtual coordinates var int y
New vertical position in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_movetopxl","title":"Bar_MoveToPxl
","text":"Bar_MoveToPxl
Move the bar to pixel position.
func void Bar_MoveToPxl(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New horizontal position in pixels var int y
New vertical position in pixels "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setalpha","title":"Bar_SetAlpha
","text":"Bar_SetAlpha
Sets the transparency of the bar.
func void Bar_SetAlpha(var int bar, var int alpha)\n
Parameters var int bar
Handle returned from Bar_Create
var int alpha
Transparency value (0..255) "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setbartexture","title":"Bar_SetBarTexture
","text":"Bar_SetBarTexture
Sets the foreground texture of the bar.
func void Bar_SetBarTexture(var int bar, var string barTex)\n
Parameters var int bar
Handle returned from Bar_Create
var string barTex
The new foreground texture "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_setbacktexture","title":"Bar_SetBackTexture
","text":"Bar_SetBackTexture
Sets the background texture of the bar.
func void Bar_SetBackTexture(var int bar, var string backTex)\n
Parameters var int bar
Handle returned from Bar_Create
var string backTex
The new background texture "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_resize","title":"Bar_Resize
","text":"Bar_Resize
Resize an existing bar.
func void Bar_Resize(var int bar, var int width, var int height)\n
Parameters var int bar
Handle returned from Bar_Create
var int width
New width in virtual coordinates var int height
New height in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/bars/#bar_resizepxl","title":"Bar_ResizePxl
","text":"Bar_ResizePxl
Resize existing bar (in pixels).
func void Bar_ResizePxl(var int bar, var int x, var int y)\n
Parameters var int bar
Handle returned from Bar_Create
var int x
New width in pixels var int y
New height in pixels "},{"location":"zengin/scripts/extenders/lego/applications/bars/#examples","title":"Examples","text":"Note
The bars assume a certain basic understanding of the PermMem module.
"},{"location":"zengin/scripts/extenders/lego/applications/bars/#a-dedicated-experience-bar","title":"A dedicated experience bar","text":"Bars implement the Bar
class. It looks like this:
class Bar\n{\n var int x; // X position on the screen (middle of the bar)\n var int y; // Y position on the screen (middle of the bar)\n var int barTop; // Top/bottom margin\n var int barLeft; // Left/right margin\n var int width; // Bar width\n var int height; // Bar height\n var string backTex; // Background texture\n var string barTex; // Actual bar texture\n var int value; // Current value\n var int valueMax; // Maximum value\n};\n
The GothicBar
prototype is a bar, which mimics the standard Gothic status bar. prototype GothicBar(Bar)\n{\n x = Print_Screen[PS_X] / 2;\n y = Print_Screen[PS_Y] - 20;\n barTop = 3;\n barLeft = 7;\n width = 180;\n height = 20;\n backTex = \"Bar_Back.tga\";\n barTex = \"Bar_Misc.tga\";\n value = 100;\n valueMax = 100;\n};\n
It is much easier to set up a new instance using this prototype. GothicBar
without modifications can be found as the GothicBar@
instance, which we used to create the bar in the example above. GothicBar
is located in the middle of the screen and looks exactly like the Gothic underwater bar.
// Instance created from \ninstance Bar_1(GothicBar)\n{\n x = 100;\n y = 20;\n};\n\nfunc void Example_1()\n{\n // Example_1 could e.g. be called in Init_Global\n FF_ApplyOnce(Loop_1);\n};\n\nfunc void Loop_1()\n{\n // Example_1 gets this loop running.\n // Here the bar should be constructed once\n // and then adapted to the EXP of the hero:\n var int MyBar;\n if(!Hlp_IsValidHandle(MyBar))\n {\n MyBar = Bar_Create(Bar_1); // Our Bar_1\n };\n // The rest is probably self-explanatory:\n Bar_SetMax(MyBar, hero.exp_next);\n Bar_SetValue(MyBar, hero.exp);\n};\n
Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/","title":"Bloodsplats","text":""},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplats","title":"Bloodsplats","text":"Info
Dependencies: - Floats - View - Random - Anim8 Implementation: Bloodsplats.d on GitHub
If this package is activated, red blood splatters will appear on the screen when the hero takes damage. For this, the damage perception for the hero is redirected to _B_HeroDamage()
. To use the Bloodsplats, the enclosed textures must be available. Also, the VFX \"HERO_HURT\" (also included) should be entered in the VfxInst.d
to create an even better hit effect. All textures used here are from CGTextures.com. If you use Bloodsplats in your modification, this site must be noted in the credits.
Tip
See user constants to edit behavior of this packet.
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#initialization","title":"Initialization","text":"Initialize with LeGo_Bloodsplats
flag.
LeGo_Init(LeGo_Bloodsplats);\n
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplat","title":"Bloodsplat
","text":"Bloodsplat
Puts a blood splatter on the screen.
func void Bloodsplat(var int damage)\n
Parameters var int damage
The damage (affects the size of the splatter) "},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#bloodsplats_rage","title":"Bloodsplats_Rage
","text":"Bloodsplats_Rage
Pretty pointless feature that smears the entire screen.
func void Bloodsplats_Rage()\n
"},{"location":"zengin/scripts/extenders/lego/applications/bloodsplats/#npc_getpercfunc","title":"Npc_GetPercFunc
","text":"Npc_GetPercFunc
oCNpc::GetPerceptionFunc
engine function wrapper
func int Npc_GetPercFunc(var C_Npc npc, var int type)\n
Parameters var C_NPC npc
NPC whose perception is checked var int type
Checked perception type (form Constant.d
) Return value
The function returns the state of NPCs selected perception.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/","title":"Buffs","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buffs","title":"Buffs","text":"Info
Dependencies: - PermMem - FrameFunctions Implementation: Buffs.d on GitHub
This package allows you to easily create status effects that can affect any NPC. Status effects on the hero are displayed graphically in a bar.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#initialization","title":"Initialization","text":"Initialize with LeGo_Buffs
flag.
LeGo_Init(LeGo_Buffs);\n
Warning
This package is still experimental and not included in the LeGo_All
initialization flag.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_apply","title":"Buff_Apply
","text":"Buff_Apply
Applies a status effect to an NPC.
func int Buff_Apply(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_applyunique","title":"Buff_ApplyUnique
","text":"Buff_ApplyUnique
Buff_Apply
, but nothing happens if a status effect of that kind is already on the NPC.
func int Buff_ApplyUnique(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated or 0
if the buff is already applied on the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_applyorrefresh","title":"Buff_ApplyOrRefresh
","text":"Buff_ApplyOrRefresh
Buff_Apply
, but if a status effect of this type is already affecting the NPC, the duration will be reset.
func int Buff_ApplyOrRefresh(var C_NPC n, var int buff)\n
Parameters Return value
The function returns the handle of the buff, which was just generated or refreshed.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_refresh","title":"Buff_Refresh
","text":"Buff_Refresh
Resets the duration of the buff.
func void Buff_Refresh(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff to refresh "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_remove","title":"Buff_Remove
","text":"Buff_Remove
Removes the buff from the all NPCs.
func void Buff_Remove(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff to remove "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_removeall","title":"Buff_RemoveAll
","text":"Buff_RemoveAll
Removes the buffs form the NPC.
func void Buff_RemoveAll(var C_NPC npc, var int buffInstance)\n
Parameters var C_NPC npc
NPC whose buff should be removed "},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_getnpc","title":"Buff_GetNpc
","text":"Buff_GetNpc
Returns a pointer to the NPC, which is affected by the buff.
func int Buff_GetNpc(var int buffHandle)\n
Parameters var int buffHandle
Handle of the buff Return value
The function returns a pointer to the NPC, which is affected by the buff.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#buff_has","title":"Buff_Has
","text":"Buff_Has
Checks if the NPC already has an effect applied.
func int Buff_Has(var C_NPC npc, var int buff)\n
Parameters Return value
The function returns TRUE
if the NPC has an effect applied. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#save_getfuncid","title":"SAVE_GetFuncID
","text":"SAVE_GetFuncID
Same as MEM_GetFuncID
but gets the current instance.
func int SAVE_GetFuncID(var func f)\n
Parameters var func f
Function whose ID is got
Return value
The function returns the ID of given function.
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#lcbuff-class","title":"lCBuff class","text":"The buffs package implements an lCBuff
class, which looks like this:
class lCBuff\n{\n var string name; // buff name \n var int buffType; // GOOD / NEUTRAL / BAD | 1 / 0 / -1\n var int targetID; // NPC that is currently affected by this buff\n var int durationMS; // buff duration in milliseconds\n var int tickMS; // tick duration in milliseconds, first tick occurs at tickMS milliseconds\n var int nextTickNr; // e.g. before the first tick this will be 0; OBSOLETE, remove when possible\n\n var int OnApply; \n var int OnTick;\n var int OnRemoved;\n\n var string buffTex; // associated texture - currently only used for buffs applied on the hero\n // var int originID; // Who casted/created this buff?\n\n // Internal, no need to set during instance construction\n var int _startedTime;\n var int _endTime; // Not redundant with durationMS because buffs can be refreshed\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/buffs/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/buffs/#delayed-poison","title":"Delayed poison","text":"instance deadly_poison(lCBuff)\n{\n name = \"Deadly poison\";\n bufftype = BUFF_BAD;\n\n durationMS = 10*1000; // 10 seconds long\n tickMS = 1000; // Every second\n\n buffTex = \"POISON.TGA\";\n};\n
Damage should also be added:
func void deadly_poison_damage(var int buffHandle)\n{\n var int ptr; ptr = Buff_GetNpc(buffHandle);\n if (!ptr) { return; }; // Can happen if e.g. the world was changed\n\n var C_NPC npc; npc = _^(ptr);\n Npc_ChangeAttribute(npc, ATR_HITPOINTS, -3); // 3 damage\n};\n
For complicated technical reasons we use the function SAVE_GetFuncID
instead of MEM_GetFuncID
. instance deadly_poison(lCBuff)\n{\n name = \"Deadly poison\";\n bufftype = BUFF_BAD;\n\n durationMS = 10 * 1000; //10 seconds long\n tickMS = 1000; // Every second\n\n onTick = SAVE_GetFuncID(deadly_poison_damage); // The damage should be applied every second\n buffTex = \"POISON.TGA\";\n};\n
For example, if this buff is now applied to the hero, by calling Buff_Apply(hero, deadly_poison)
, he loses a total of 30 HP over 10 seconds.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/","title":"Buttons","text":""},{"location":"zengin/scripts/extenders/lego/applications/buttons/#buttons","title":"Buttons","text":"Info
Dependencies: - PermMem - View Implementation: Buffs.d on GitHub
This package extends the handling of the mouse and allows creating rectangular buttons, which react to mouse (hover) entry and exit as well as a mouse click.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#initialization","title":"Initialization","text":"Initialize with LeGo_Buttons
flag.
LeGo_Init(LeGo_Buttons);\n
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_create","title":"Button_Create
","text":"Button_Create
Creates a button. It is initially hidden (not visible and does not react to the mouse). The three callback functions have the following signature void f(int handle)
.
func int Button_Create(var int posx, var int posy, var int width, var int height, var string tex, var func on_enter, var func on_leave, var func on_click)\n
Parameters var int posx
The horizontal position of the button in virtual coordinates var int posy
The vertical position of the button in virtual coordinates var int width
Width of the button in virtual coordinates var int height
Height of the button in virtual coordinates var string tex
Name of the button texture var func on_enter
This function is called when the mouse enters the button var func on_leave
This function is called when the mouse leaves the button var func on_click
This function is called when the user performs a mouse click on the button (left mouse button) Return value
The function returns a handle to created button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_createpxl","title":"Button_CreatePxl
","text":"Button_CreatePxl
Button_Create
with pixels instead of virtual coordinates.
func int Button_CreatePxl(var int posx, var int posy, var int width, var int height, var string tex, var func on_enter, var func on_leave, var func on_click)\n
Parameters var int posx
The horizontal position of the button in pixels var int posy
The vertical position of the button in pixels var int width
Width of the button in pixels var int height
Height of the button in pixels var string tex
Name of the button texture var func on_enter
This function is called when the mouse enters the button var func on_leave
This function is called when the mouse leaves the button var func on_click
This function is called when the user performs a mouse click on the button (left mouse button) Return value
The function returns a handle to created button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_delete","title":"Button_Delete
","text":"Button_Delete
Completely deletes a button.
func void Button_Delete(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_show","title":"Button_Show
","text":"Button_Show
Shows the button and makes it respond to the mouse.
func void Button_Show(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_hide","title":"Button_Hide
","text":"Button_Hide
Hides the button and disables it, so it is no longer responding to the mouse.
func void Button_Hide(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_settexture","title":"Button_SetTexture
","text":"Button_SetTexture
Sets the texture of the button.
func void Button_SetTexture(var int hndl, var string tex)\n
Parameters var int hndl
Handle returned from Button_Create
var string tex
Name of the new texture "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_setcaption","title":"Button_SetCaption
","text":"Button_SetCaption
Displays a centered text on the button.
func void Button_SetCaption(var int hndl, var string caption, var string font)\n
Parameters var int hndl
Handle returned from Button_Create
var string caption
The text to be displayed var string font
The font in which the text should be displayed "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_createmouseover","title":"Button_CreateMouseover
","text":"Button_CreateMouseover
Attaches a mouseover box to the cursor.
func void Button_CreateMouseover(var string text, var string font)\n
Parameters var string text
The text in the mouseover box var string font
The font of the text "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_deletemouseover","title":"Button_DeleteMouseover
","text":"Button_DeleteMouseover
Deletes the mouseover box.
func void Button_DeleteMouseover()\n
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_activate","title":"Button_Activate
","text":"Button_Activate
Activates the button, so it reacts to the mouse. Does not change the visibility.
func void Button_Activate(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_deactivate","title":"Button_Deactivate
","text":"Button_Deactivate
Disables the button, so it no longer reacts to the mouse.
func void Button_Deactivate(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_setuserdata","title":"Button_SetUserData
","text":"Button_SetUserData
Sets the user data of the button, an integer, to give the button individual information.
func void Button_SetUserData(var int hndl, var int data)\n
Parameters var int hndl
Handle returned from Button_Create
var int data
Individual integer of the button (part of the internal _Button
class) "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getuserdata","title":"Button_GetUserData
","text":"Button_GetUserData
Gets the user data of the button.
func int Button_GetUserData(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the user data of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getstate","title":"Button_GetState
","text":"Button_GetState
Gets the status of the button as a bit field. See User Constants.
func int Button_GetState(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the status of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_move","title":"Button_Move
","text":"Button_Move
Moves the button by the given value in pixels. posx = posx + nposx
func void Button_Move(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
X-axis shift in pixels var int nposy
Y-axis shift in pixels "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_movevrt","title":"Button_MoveVrt
","text":"Button_MoveVrt
Moves the button by the given value in virtual coordinates. posx = posx + nposx
func void Button_Move(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
X-axis shift in virtual coordinates var int nposy
Y-axis shift in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_moveto","title":"Button_MoveTo
","text":"Button_MoveTo
Moves a button to the given position in pixels. posx = nposx
func void Button_MoveVrt(var int hndl, var int nposx, var int nposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nposx
New horizontal position in pixels var int nposy
New vertical position in pixels "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_movetovrt","title":"Button_MoveToVrt
","text":"Button_MoveToVrt
Moves a button to the given position in virtual coordinates. posx = nvposx
func void Button_MoveVrt(var int hndl, var int nvposx, var int nvposy)\n
Parameters var int hndl
Handle returned from Button_Create
var int nvposx
New horizontal position in virtual coordinates var int nvposy
New vertical position in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getviewhandle","title":"Button_GetViewHandle
","text":"Button_GetViewHandle
Returns the button's zCView
as a handle.
func int Button_GetViewHandle(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as a handle.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getviewptr","title":"Button_GetViewPtr
","text":"Button_GetViewPtr
Returns the button's zCView
as a pointer.
func int Button_GetViewPtr(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as a pointer.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getview","title":"Button_GetView
","text":"Button_GetView
Returns the button's zCView
as an object.
func zCView Button_GetView(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the button's zCView
as an object.
"},{"location":"zengin/scripts/extenders/lego/applications/buttons/#button_getcaptionptr","title":"Button_GetCaptionPtr
","text":"Button_GetCaptionPtr
Returns the pointer to the text of the button.
func int Button_GetCaptionPtr(var int hndl)\n
Parameters var int hndl
Handle returned from Button_Create
Return value
The function returns the pointer to the text of the button.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/","title":"Console Commands","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#console-commands","title":"Console Commands","text":"Info
Dependencies: - PermMem - HookEngine Implementation: ConsoleCommands.d on GitHub
This package allows you to create new console commands.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#initialization","title":"Initialization","text":"Initialize with LeGo_ConsoleCommands
flag.
LeGo_Init(LeGo_ConsoleCommands);\n
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_register","title":"CC_Register
","text":"CC_Register
Registers a new console command.
func void CC_Register(var func f, var string cmdPrefix, var string description)\n
Parameters var func f
This function is executed when the cmdPrefix
command is entered in the console. The function signature is func string f(var string p0)
. The string passed is everything that was specified in the console after the actual command. The return value is then displayed in the console. var string cmdPrefix
This is a command, which can be entered in the console. var string description
This text appears next to the command (in zSpy) when you use the help
command in the console. "},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_remove","title":"CC_Remove
","text":"CC_Remove
Removes a function from the console commands.
func void CC_Remove(var func f)\n
Parameters var func f
This function will be removed, i.e. the associated command will no longer work. "},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#cc_active","title":"CC_Active
","text":"CC_Active
Checks whether the function passed is already part of a console command.
func int CC_Active(var func f)\n
Parameters var func f
Function being checked Return value
The function returns TRUE
if there is a corresponding function, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/console_commands/#basic-command-example","title":"Basic command example","text":"As a basic example - let us create a version command, which prints a version of our modification. Firstly, we declare a constant string
variable to hold the version string to be shown.
const string Mod_Version = \"My mod version 0.1alpha\";\n
Next we create the command function. Note
Notice the correct function signature. If you do not adhere to the correct function signature, the command will crash the game.
// This function is called by our console\nfunc string CC_ModVersion(var string param)\n{\n return Mod_Version;\n};\n
We then have to register the functions. For convenience, I created a new RegisterConsoleFunctions
function to initialize all console commands. The function is really simple. func void RegisterConsoleFunctions()\n{\n CC_Register (CC_ModVersion, \"version\", \"Version of my amazing mod.\");\n};\n
Lastly, we have to call this function from INIT_GLOBAL
function. func void INIT_GLOBAL()\n{\n // will be called for every world (from INIT_<LevelName>)\n Game_InitGerman();\n\n // Ikarus initialization\n MEM_InitAll();\n\n // LeGo initialization\n LeGo_Init(LeGo_ConsoleCommands);\n\n // Here we register all of our commands\n RegisterConsoleFunctions();\n\n // the rest of the code \n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/","title":"Cursor","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor","title":"Cursor","text":"Info
Dependencies: - Floats - FrameFunctions - View Implementation: Cursor.d on GitHub
This package implements Gothic in-game mouse cursor support. To visually display the cursor there is a Cursor.tga
file in the resources, but the texture can be changed in user constants.
Warning
The cursor only works if the mouse is activated in the Gothic settings. It can be done directly from the scripts. See the Ini file access.
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#initialization","title":"Initialization","text":"Initialize with LeGo_Cursor
flag.
LeGo_Init(LeGo_Cursor);\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#variables","title":"Variables","text":" var int Cursor_X
Always contains the X coordinate of the mouse cursor. var int Cursor_Y
Always contains the Y coordinate of the mouse cursor. var float Cursor_RelX
Always contains the relative X coordinate of the mouse cursor as an Ikarus float. var float Cursor_RelY
Always contains the relative Y coordinate of the mouse cursor as an Ikarus float. var int Cursor_Wheel
Variable containing the value of the mouse wheel. var int Cursor_Left
Variable that always contains the KeyState of the left mouse button. var int Cursor_Mid
Variable that always contains the KeyState of the middle mouse button. var int Cursor_Right
Variable that always contains the KeyState of the right mouse button. var int Cursor_Event
An event handler that can send information about the mouse cursor. It can be used with all functions of the EventHandler package. var int Cursor_NoEngine
Variable that can prevent the engine from working. If is set to TRUE
the engine no longer reacts to mouse movements. "},{"location":"zengin/scripts/extenders/lego/applications/cursor/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor_hide","title":"Cursor_Hide
","text":"Cursor_Hide
Hides the displayed mouse cursor.
func void Cursor_Hide()\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#cursor_show","title":"Cursor_Show
","text":"Cursor_Show
Shows the mouse cursor.
func void Cursor_Show()\n
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#setmouseenabled","title":"SetMouseEnabled
","text":"SetMouseEnabled
Can manually enable or disable the mouse.
func void SetMouseEnabled(var int enabled)\n
Parameters var int enabled
TRUE
- Mouse activated "},{"location":"zengin/scripts/extenders/lego/applications/cursor/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/cursor/#click-a-button","title":"Click a button","text":"We use a View to display a button to be clicked. The FrameFunctions take care of the loop to check whether a click was made.
var int Button;\nfunc void Example1()\n{\n // We show the cursor and at the same time a button to be clicked:\n Cursor_Show();\n\n // New View:\n Button = View_CreatePxl(5, 5, 125, 50);\n View_SetTexture(Button, \"BUTTONTEX.TGA\");\n View_Open(Button);\n\n // Optionally, mouse can be switched off for the engine:\n Cursor_NoEngine = true; // -> The engine then no longer reacts to movements, so the camera does not move either\n\n // Enable loop function:\n FF_ApplyOnce(Button_Click);\n};\n\nfunc void Button_Click()\n{\n if(Cursor_Left != KEY_PRESSED) { return; }; // Exit the function if the left mouse button was not pressed\n\n if(Cursor_X >= 5 && Cursor_X <= 125\n && Cursor_Y >= 5 && Cursor_Y <= 50) // Simply take over the coordinates of the view\n { \n // Here the button was clicked.\n // Remove button and end loop:\n View_Close(Button);\n View_Delete(Button);\n Button = 0;\n\n // Allow the engine to continue working:\n Cursor_NoEngine = false;\n\n FF_Remove(Button_Click);\n\n // Hide the mouse:\n Cursor_Hide();\n };\n};\n
This also can be done by the Buttons package instead of View.
"},{"location":"zengin/scripts/extenders/lego/applications/cursor/#event-handler","title":"Event handler","text":"Since LeGo 2.2 there is also an event handler (var int Cursor_Event
) in the cursor package. This example briefly explains how it works:
func void Example2()\n{\n // We register MyCursorListener as the handler/listener of the Cursor_Event:\n Event_Add(Cursor_Event, MyCursorListener);\n\n // From now on, MyCursorListener will be called whenever the cursor has something to report.\n};\n\nfunc void MyCursorListener(var int state)\n{\n // The rest is self-explanatory:\n\n if(state == CUR_WheelUp)\n {\n PrintS(\"Wheel up!\");\n };\n if(state == CUR_WheelDown)\n {\n PrintS(\"Wheel down!\");\n };\n if(state == CUR_LeftClick)\n {\n PrintS(\"Leftclick!\");\n };\n if(state == CUR_RightClick)\n {\n PrintS(\"Rightclick!\");\n };\n if(state == CUR_MidClick)\n {\n PrintS(\"Wheelclick!\");\n };\n};\n
Constants used in the example can be found in the user constants."},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/","title":"Dialoggestures","text":""},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#dialoggestures","title":"Dialoggestures","text":"Info
Dependencies: - AI_Function Implementation: Dialoggestures.d on GitHub
This package can modify the NPCs' gestures during dialogue to better bring out emotions.
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag","title":"DIAG
","text":"DIAG
With this function the dialog gestures for all NPCs can be overridden. To understand the principle, it is recommended to take a look at the examples.
The full name of the animation can be described as follows:
DIAG_Prefix + aniName + DIAG_Suffix + ((rand() % (max - (min - 1))) + min).ToString(\"00\");\n
DIAG_Prefix
and DIAG_Suffix
are user constants.
func void DIAG(var string AniName, var int Min, var int Max)\n
Parameters var string AniName
The new dialogue gesture var int Min
Lowest animation number var int Max
Highest animation number "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_reset","title":"DIAG_Reset
","text":"DIAG_Reset
Resets the dialog gestures to the default.
func void DIAG_Reset()\n
"},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_setani","title":"DIAG_SetAni
","text":"DIAG_SetAni
Sets animation directly.
func void DIAG_SetAni(var string AniName)\n
Parameters var string AniName
Animation name "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#diag_setminmax","title":"DIAG_SetMinMax
","text":"DIAG_SetMinMax
Sets animation numbers directly.
func void DIAG_SetMinMax(var int min, var int max)\n
Parameters var int min
Lowest animation number var int max
Highest animation number "},{"location":"zengin/scripts/extenders/lego/applications/dialoggestures/#examples","title":"Examples","text":"Note
See Examples in the Trialoge article.
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/","title":"Focusnames","text":""},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames","title":"Focusnames","text":"Info
Dependencies: - Interface - HookEngine Implementation: Focusnames.d on GitHub
This package colors the focus names of the NPCs in appropriate colors according to the behavior defined below (alpha values are taken into account). Also affects monsters. (Mobs/Items get Color_Neutral)
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#initialization","title":"Initialization","text":"Initialize with LeGo_Focusnames
flag.
LeGo_Init(LeGo_Focusnames);\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#usage","title":"Usage","text":"If you want to change colors for any behavior edit the following functions directly in Focusnames.d
file.
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_friendly","title":"Focusnames_Color_Friendly
","text":"Focusnames_Color_Friendly
func int Focusnames_Color_Friendly()\n{\n return RGBA(0, 255, 0, 255); // Green\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_neutral","title":"Focusnames_Color_Neutral
","text":"Focusnames_Color_Neutral
func int Focusnames_Color_Neutral()\n{\n return RGBA(255, 255, 255, 255); // White\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_angry","title":"Focusnames_Color_Angry
","text":"Focusnames_Color_Angry
func int Focusnames_Color_Angry()\n{\n return RGBA(255, 180, 0, 255); // Orange\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/focusnames/#focusnames_color_hostile","title":"Focusnames_Color_Hostile
","text":"Focusnames_Color_Hostile
func int Focusnames_Color_Hostile()\n{\n return RGBA(255, 0, 0, 255); // Red\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/","title":"Gamestate","text":""},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate","title":"Gamestate","text":"Info
Dependencies: - EventHandler - Saves Implementation: Gamestate.d on GitHub
Gamestate package allows to check for different game states (game start, game load or level change).
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#initialization","title":"Initialization","text":"Initialize with LeGo_Gamestate
flag.
LeGo_Init(LeGo_Gamestate);\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate_addlistener","title":"Gamestate_AddListener
","text":"Gamestate_AddListener
Adds a listener/handler to the game-state event.
func void Gamestate_AddListener(var func listener)\n
Parameters var func listener
This function will be called on a game-state change. The current game-state is passed as a parameter. "},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#gamestate_removelistener","title":"Gamestate_RemoveListener
","text":"Gamestate_RemoveListener
Removes game-state listener.
func void Gamestate_RemoveListener(var func listener)\n
Parameters var func listener
Listener function to be removed. "},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#examples","title":"Examples","text":"There are now two possibilities. Everything can be done directly into the Init_Global
, or with EventHandler.
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#init_global","title":"Init_Global","text":"func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n if(Gamestate == Gamestate_NewGame) \n {\n MEM_Info(\"New game started.\");\n }\n else if(Gamestate == Gamestate_Loaded)\n {\n MEM_Info(\"Game loaded.\");\n }\n else if(Gamestate == Gamestate_WorldChange)\n {\n MEM_Info(\"Worldshift.\");\n }\n else\n {\n MEM_Info(\"I don't pass.\");\n };\n};\n
It can also be done like that:
func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n if(Gamestate == Gamestate_NewGame)\n {\n FF_Apply(MyLoop);\n FF_Apply(My2ndLoop);\n };\n};\n
This would have the same effect as: func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n FF_ApplyOnce(MyLoop);\n FF_ApplyOnce(My2ndLoop);\n};\n
"},{"location":"zengin/scripts/extenders/lego/applications/gamestate/#eventhandler","title":"EventHandler","text":"func void Init_Global()\n{\n // [...]\n\n LeGo_Init(LeGo_All);\n\n Gamestate_AddListener(MyGamestateListener);\n};\n\nfunc void MyGamestateListener(var int state)\n{\n if(state == Gamestate_NewGame)\n {\n MEM_Info(\"New game started.\");\n }\n else if(state == Gamestate_Loaded)\n {\n MEM_Info(\"Game loaded.\");\n }\n else if(state == Gamestate_WorldChange)\n {\n MEM_Info(\"Worldshift.\");\n }\n else\n {\n MEM_Info(\"I don't pass.\");\n };\n};\n
This is the same as the Init_Global
example, but it may look more elegant to some. Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/applications/names/","title":"Names","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#names","title":"Names","text":"Info
Dependencies: - Talents Implementation: Names.d on GitHub
Allows the user to change NPC name e.g. after he shows up.
"},{"location":"zengin/scripts/extenders/lego/applications/names/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/applications/names/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#setname","title":"SetName
","text":"SetName
Should be set in InitGlobal().
func void SetName(var C_NPC npc, var string name)\n
Parameters var C_NPC npc
The NPC to be named var string name
The name of the NPC "},{"location":"zengin/scripts/extenders/lego/applications/names/#showname","title":"ShowName
","text":"ShowName
Permanently displays the name set by SetName
function above the npc.
func void ShowName(var C_NPC npc)\n
Parameters var C_NPC npc
The NPC whose name should be shown "},{"location":"zengin/scripts/extenders/lego/applications/names/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/names/#show-the-name-of-an-npc-later","title":"Show the name of an NPC later","text":"instance PAL_100_Friend(C_NPC)\n{\n name = \"Paladin\";\n\n // [...]\n};\n\nfunc void Init_Global()\n{\n SetName(PAL_100_Friend, \"Arto\");\n};\n
At the start of the game, the name \"Paladin\" is displayed above PAL_100_Friend
. If ShowName(PAL_100_Friend);
is used during a dialogue, the name \"Arto\" is permanently visible above the npc.
"},{"location":"zengin/scripts/extenders/lego/applications/render/","title":"Render","text":""},{"location":"zengin/scripts/extenders/lego/applications/render/#render","title":"Render","text":"Info
Dependencies: - List - View - PermMem Implementation: Render.d on GitHub
With this package items can be rendered on the screen. Since items are rendered independently of the normal views, textures that are 'below' the items must also be managed by this package, this behaviour is managed by the priority system. The view with the highest priority is always rendered first, so it is at the bottom. In theory, any .3DS model can be rendered if you just create a suitable item script.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#initialization","title":"Initialization","text":"Initialize with LeGo_Render
flag.
LeGo_Init(LeGo_Render);\n
Warning
This package is still experimental and not included in LeGo_All
initialization flag.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/render/#render_additemprio","title":"Render_AddItemPrio
","text":"Render_AddItemPrio
Generates the render of an item, with a manually specified priority.
func int Render_AddItemPrio(var int itemInst, var int x1, var int y1, var int x2, var int y2, var int priority)\n
Parameters var int itemInst
The instance of the item to render var int x1
var int y1
The top left coordinate of the view var int x2
var int y2
The bottom right coordinate of the view var int priority
The priority of this render object Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_additem","title":"Render_AddItem
","text":"Render_AddItem
Generates the render of an item, with priority set to 0
.
func int Render_AddItem(var int itemInst, var int x1, var int y1, var int x2, var int y2)\n
Parameters var int itemInst
The instance of the item to render var int x1
var int y1
The top left coordinate of the view var int x2
var int y2
The bottom right coordinate of the view Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_addviewprio","title":"Render_AddViewPrio
","text":"Render_AddViewPrio
Generates the render of a View, with a manually specified priority.
func int Render_AddViewPrio(var int view, var int priority)\n
Parameters var int view
A handle to a View var int priority
The priority of this render object Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_addview","title":"Render_AddView
","text":"Render_AddView
Generates the render of a View, with priority set to 0
.
func int Render_AddView(var int view)\n
Parameters var int view
A handle to a View Return value
The function returns a handle of the render object.
"},{"location":"zengin/scripts/extenders/lego/applications/render/#render_openview","title":"Render_OpenView
","text":"Render_OpenView
Opens a render object. Only open render objects are displayed.
func void Render_OpenView(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/render/#render_closeview","title":"Render_CloseView
","text":"Render_CloseView
Closes a render object. Only open render objects are displayed.
func void Render_CloseView(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/render/#render_remove","title":"Render_Remove
","text":"Render_Remove
Deletes a render object. The associated view is deleted automatically.
func void Render_Remove(var int handle)\n
Parameters var int handle
Handle of a render object "},{"location":"zengin/scripts/extenders/lego/applications/saves/","title":"Saves","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#saves","title":"Saves","text":"Info
Dependencies: - BinaryMachines Implementation: Saves.d on GitHub
Offers an open file stream that can read/write variables on save/load. It is used by PermMem, so you don't need to address it manually anymore.
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#initialization","title":"Initialization","text":"Initialize with LeGo_Saves
flag.
LeGo_Init(LeGo_Saves);\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#bw_savegame","title":"BW_Savegame
","text":"BW_Savegame
Custom function. It creates a stream to its own memory file, this can be filled with the BW_*
functions from the BinaryMachines.
func void BW_Savegame()\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#br_savegame","title":"BR_Savegame
","text":"BR_Savegame
Custom function. It opens a stream to a previously saved memory file, which can be read from the BinaryMachines using the BR_*
functions.
func void BR_Savegame()\n
"},{"location":"zengin/scripts/extenders/lego/applications/saves/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/saves/#save-a-high-score-list","title":"Save a high score list","text":"var string MyScoreList[10];\n
Since strings are not saved by the game by default, we use the functions from Saves.d
to create an additional memory file that only belongs to us. At the top the Saves.d file has two functions: BW_Savegame
and BR_Savegame
. BinaryMachines functions are used to save or read the file, we don't need to do anything else than to use them here, the rest is done by Saves.d
completely by itself. Therefore, we only modify these two functions.
func void BW_Savegame() \n{\n // Save high score list\n BW_String(MyScoreList[0]);\n BW_String(MyScoreList[1]);\n BW_String(MyScoreList[2]);\n BW_String(MyScoreList[3]);\n BW_String(MyScoreList[4]);\n BW_String(MyScoreList[5]);\n BW_String(MyScoreList[6]);\n BW_String(MyScoreList[7]);\n BW_String(MyScoreList[8]);\n BW_String(MyScoreList[9]);\n};\n\nfunc void BR_Savegame() \n{\n // Load high score list\n MyScoreList[0] = BR_String();\n MyScoreList[1] = BR_String();\n MyScoreList[2] = BR_String();\n MyScoreList[3] = BR_String();\n MyScoreList[4] = BR_String();\n MyScoreList[5] = BR_String();\n MyScoreList[6] = BR_String();\n MyScoreList[7] = BR_String();\n MyScoreList[8] = BR_String();\n MyScoreList[9] = BR_String();\n};\n
Tip
Since LeGo 2.0, such things can be implemented much more elegantly with PermMem.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/","title":"Trialoge","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#trialoge","title":"Trialoge","text":"Info
Dependencies: - AI_Function Implementation: Trialoge.d on GitHub
This package allows you to create conversations with any number of NPCs and control the camera during the dialog.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#initialization","title":"Initialization","text":"Initialize with LeGo_Trialoge
flag.
LeGo_Init(LeGo_Trialoge);\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#equipweapon","title":"EquipWeapon
","text":"EquipWeapon
Sektenspinner's function. Makes NPC equip a weapon.
func void EquipWeapon(var C_NPC slf, var int ItemInstance)\n
Parameters var C_NPC slf
NPC to have a weapon equipped var int ItemInstance
Weapon instance ID to be equipped Configuration
const int EquipWeapon_TogglesEquip = 1
Above constant configures the behaviour of the function when trying to equip an already equipped weapon:
0
- EquipWeapon
will do nothing 1
- EquipWeapon
will unequip this weapon "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getarmor","title":"Npc_GetArmor
","text":"Npc_GetArmor
Returns NPC's equipped armor.
func int Npc_GetArmor(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get the armor from Return value
The function returns instance of armor worn by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getmeleeweapon","title":"Npc_GetMeleeWeapon
","text":"Npc_GetMeleeWeapon
Returns NPC's equipped melee weapon.
func int Npc_GetMeleeWeapon(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get the weapon from Return value
The function returns instance ID of melee weapon equipped by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_getrangedweapon","title":"Npc_GetRangedWeapon
","text":"Npc_GetRangedWeapon
Returns NPC's equipped ranged weapon.
func int Npc_GetRangedWeapon(var c_npc slf)\n
Parameters var C_NPC slf
NPC to get the weapon from Return value
The function returns instance ID of ranged weapon equipped by the NPC.
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#npc_tradeitem","title":"Npc_TradeItem
","text":"Npc_TradeItem
Swaps NPCs equipped weapon.
func void Npc_TradeItem(var c_npc slf, var int itm0, var int itm1) \n
Parameters var C_NPC slf
NPC to perform operation on var int itm0
instance ID of item to remove var int itm1
instance ID of item to create and equip "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_update","title":"DiaCAM_Update
","text":"DiaCAM_Update
Sektenspinner's function that updates the dialogue camera. (Used internally.)
func void DiaCAM_Update()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_disable","title":"DiaCAM_Disable
","text":"DiaCAM_Disable
Completely disable the dialogue cameras.
func void DiaCAM_Disable()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#diacam_enable","title":"DiaCAM_Enable
","text":"DiaCAM_Enable
Resets the dialogue cameras to the default settings.
func void DiaCAM_Enable()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_wait","title":"TRIA_Wait
","text":"TRIA_Wait
Makes self
and other
wait for each other, e.g. for AI_GotoWP
actions for synchronization.
func void TRIA_Wait()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_invite","title":"TRIA_Invite
","text":"TRIA_Invite
Invites an NPC into a conversation. Must be called before TRIA_Start
.
func void TRIA_Invite(var C_NPC slf)\n
Parameters var C_NPC slf
The invited NPC "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_start","title":"TRIA_Start
","text":"TRIA_Start
Starts trialogues. Before that, all NPCs should be invited by TRIA_Invite
.
func void TRIA_Start()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_barrier","title":"TRIA_Barrier
","text":"TRIA_Barrier
Similar to TRIA_Wait
but applies to all participating NPCs.
func void TRIA_Barrier()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_next","title":"TRIA_Next
","text":"TRIA_Next
Sets the called npc to self
.
func void TRIA_Next(var C_NPC n0)\n
Parameters var C_NPC n0
NPC to set to self
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_cam","title":"TRIA_Cam
","text":"TRIA_Cam
Starts a tracking shot.
func void TRIA_Cam(var string evt)\n
Parameters var string evt
The name of the tracking shot in Spacer. If \"\"
is passed, the running trace shot will be aborted. "},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#tria_finish","title":"TRIA_Finish
","text":"TRIA_Finish
Ends an ongoing trialogue. Must always be called at the end, otherwise no further trialogues can be started.
func void TRIA_Finish()\n
"},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/applications/trialoge/#a-simple-trialogue","title":"A Simple Trialogue","text":"The following conversation is resolved via the trialogues:
Arto: I'm sorry Hero, but you can't pass here. Hero: Why not? Horka: The city has been closed. Hero: I have some gold with me, can we trade? Squelto: No. We are not open to bribery. Hero: Sure? Arto: I have to ask you to leave now. Hero: Well... instance TRIA_Test (C_INFO)\n{\n npc = PAL_100_Friend;\n nr = 10;\n condition = TRIA_Test_condition;\n information = TRIA_Test_info;\n important = FALSE;\n permanent = 1;\n description = \"TRIALOGTEST\";\n};\n\nfunc int TRIA_Test_condition()\n{\n return TRUE;\n};\n\nfunc void TRIA_Test_info()\n{\n var C_NPC Arto; Arto = Hlp_GetNpc(PAL_100_Friend); // He is the owner of dialogue\n var C_NPC Horka; Horka = Hlp_GetNpc(PAL_101_Horka);\n var C_NPC Squelto; Squelto = Hlp_GetNpc(PAL_102_Squelto);\n\n TRIA_Invite(Horka); // Invite Horka into this dialogue\n TRIA_Invite(Squelto); // Invite Squelto into this dialog\n TRIA_Start(); // Start the conversation\n // The hero and Arto do not have to/may not be invited. They are in dialogue anyway.\n\n // Hero now talks to Arto (self = Arto, other = Hero)\n TRIA_Next(Arto);\n\n DIAG_Reset();\n\n AI_Output (self, other, \"TRIA_TEST_00\"); //Sorry hero, but you can't pass here.\n\n // Hero now talks to Horka (self = Horka, other = Hero)\n TRIA_Next(Horka);\n\n AI_Output (other, self, \"TRIA_TEST_01\"); //Why not?\n\n AI_GotoNpc(self, other);\n AI_TurnToNpc(other, self);\n\n AI_Output (self, other, \"TRIA_TEST_02\"); //The city has been closed.\n\n // Hero looks around conspiratorially during the next sentence\n DIAG(\"Nervous\", 1, 2);\n\n AI_Output (other, self, \"TRIA_TEST_03\"); //I have some gold with me, can we trade?\n\n // Hero should now move normally again\n DIAG_Reset();\n\n // Start tracking shot\n TRIA_Cam(\"CAMERASTART\");\n\n // Hero now talks to Squelto (self = Squelto, other = Hero)\n TRIA_Next(Squelto);\n\n AI_TurnToNpc(other, self);\n\n DIAG(\"No\", 0, 1);\n AI_Output (self, other, \"TRIA_TEST_04\"); //No. We are not open to bribery.\n\n // Hero talks to Arto again (self = Arto, other = Hero)\n TRIA_Next(Arto);\n\n // Hero should now articulate questioningly\n DIAG(\"NotSure\", 0, 1);\n\n AI_Output (other, self, \"TRIA_TEST_05\"); //Sure?\n\n AI_TurnToNpc(other, self);\n\n // tracking shot end\n TRIA_Cam(\"\");\n\n // Arto should react angrily\n DIAG(\"Angry\", 0, 4);\n\n AI_Output (self, other, \"TRIA_TEST_06\"); //I have to ask you to leave now\n\n // Hero should now move normally again\n DIAG_Reset();\n\n AI_Output (other, self, \"TRIA_TEST_07\"); //Well...\n\n TRIA_Finish(); // End\n};\n
Note
In addition, here are still Dialoggestures used.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/","title":"AI_Function","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#ai_function","title":"AI_Function","text":"Info
Dependencies: - HookEngine Implementation: AI_Function.d on GitHub
This package allows time-delayed functions to be called by enqueuing the functions in the AI queue of the NPC in question. This can be very useful in writing cutscenes on engine or implementing new routines.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#initialization","title":"Initialization","text":"Initialize with LeGo_AI_Function
flag.
LeGo_Init(LeGo_AI_Function);\n
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#ai_function_1","title":"AI_Function
","text":"AI_Function
The script function function
is called with a delay: it joins the AI queue of slf
.
func void AI_Function(var C_NPC slf, var func function)\n
Parameters var C_NPC slf
NPC in whose AI queue the function is queued var func function
Name of function to be queued Additionally, there are some overloads of AI_Function
, which allow to call functions with parameters.
func void AI_Function_I (var C_NPC slf, var func function, var int param) {}; // Int\nfunc void AI_Function_N (var C_NPC slf, var func function, var int param) {}; // Instance (e.g. NPC)\nfunc void AI_Function_S (var C_NPC slf, var func function, var string param) {}; // String\nfunc void AI_Function_II (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Int\nfunc void AI_Function_NN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Instance\nfunc void AI_Function_SS (var C_NPC slf, var func function, var string param1, var string param2) {}; // String, String\nfunc void AI_Function_IS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Int, String\nfunc void AI_Function_SI (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Int\nfunc void AI_Function_NS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Instance, String\nfunc void AI_Function_SN (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Instance\nfunc void AI_Function_IN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Instance\nfunc void AI_Function_NI (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Int\n
Functions with more than two parameters cannot be called, but parameters can be passed indirectly via global variables. In the called function, self
can be accessed as follows:
var oCNpc slf; slf = _^(ECX);\n
Info
From LeGo 2.7.2 the global instance self
is provided correctly and can be used directly.
"},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/ai_function/#enqueueing-a-simple-function","title":"Enqueueing a simple function","text":"Before a function is called, any Npc should first complete its AI queue.
Here the hero is supposed to run to a waypoint, and only when he has arrived is to start a tracking shot.
func void Example1() {\n Npc_ClearAIQueue(hero);\n AI_GotoWP(hero, \"MYWAYPOINT\");\n\n AI_Function_S(hero, Wld_SendTrigger, \"CAMERASTART\");\n};\n
As soon as the hero has reached the waypoint, Wld_SendTrigger(\"CAMERASTART\");
is called."},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/","title":"BinaryMachines","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binarymachines","title":"BinaryMachines","text":"Info
Dependencies: - None Implementation: BinaryMachines.d on GitHub
This package allows you to create and write your own files anywhere in the file system.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binarywriter","title":"BinaryWriter","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_newfile","title":"BW_NewFile
","text":"BW_NewFile
Creates the file with the file
name and opens a stream. Doesn't work if a stream is already open.
func int BW_NewFile(var string file)\n
Parameters var string file
Name of created file Return value
The function returns TRUE
if the file is successfully created and initialized, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_close","title":"BW_Close
","text":"BW_Close
Closes the current write stream.
func void BW_Close()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw","title":"BW
","text":"BW
Writes length
bytes from the data
to the stream, maximum 4 bytes.
func void BW(var int data, var int length)\n
Parameters var int data
Value of bytes var int length
Number of bytes "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_int","title":"BW_Int
","text":"BW_Int
Writes 4 bytes from the data
to the stream. Same as BW(data, 4)
.
func void BW_Int(var int data)\n
Parameters var int data
Integer value to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_char","title":"BW_Char
","text":"BW_Char
Writes the first character from the data
to the stream. Same as BW(Str_GetCharAt(data, 0), 1)
.
func void BW_Char(var string data)\n
Parameters var string data
Char to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_string","title":"BW_String
","text":"BW_String
Writes the data
terminated with \\0
to the stream.
func void BW_String(var string data)\n
Parameters var string data
String to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_byte","title":"BW_Byte
","text":"BW_Byte
Writes a byte from the data
to the stream. Same as BW(data, 1)
.
func void BW_Byte(var int data)\n
Parameters var int data
Byte value to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_bytes","title":"BW_Bytes
","text":"BW_Bytes
Writes length
of bytes from the pointer dataPtr
to the stream.
func void BW_Bytes(var int dataPtr, var int length)\n
Parameters var int dataPtr
Pointer of data to write var int length
Number of bytes "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_text","title":"BW_Text
","text":"BW_Text
Writes the string to the stream without terminating it. So it can no longer be read.
func void BW_Text(var string data)\n
Parameters var string data
Text to write "},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#bw_nextline","title":"BW_NextLine
","text":"BW_NextLine
Writes a paragraph to the stream.
func void BW_NextLine()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#binaryreader","title":"BinaryReader","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_openfile","title":"BR_OpenFile
","text":"BR_OpenFile
Opens the file with the file
name and opens a stream. Doesn't work if a stream is already open.
func int BR_OpenFile(var string file)\n
Parameters var string file
File to be opened Return value
The function returns TRUE
if the file is successfully opened and initialized, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_close","title":"BR_Close
","text":"BR_Close
Closes the current read stream.
func void BR_Close()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br","title":"BR
","text":"BR
Reads bytes from the stream.
func int BR(var int length)\n
Parameters var int length
Number of bytes to read (maximum 4) Return value
The function returns the value of read bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_int","title":"BR_Int
","text":"BR_Int
Reads 4 bytes from the stream. Same as BR(4)
.
func int BR_Int()\n
Return value The function returns the read integer.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_char","title":"BR_Char
","text":"BR_Char
Reads a character from the stream. Same as BR(1)
.
func string BR_Char()\n
Return value The function returns the read character as a string
.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_string","title":"BR_String
","text":"BR_String
Reads a string terminated by \\0
from the stream.
func string BR_String()\n
Return value The function returns the read string.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_byte","title":"BR_Byte
","text":"BR_Byte
Reads a byte from the stream.
func int BR_Byte()\n
Return value The function returns the read byte.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_bytes","title":"BR_Bytes
","text":"BR_Bytes
Reads bytes from the stream.
func int BR_Bytes(var int length)\n
Parameters var int length
Number of bytes to read Return value
The function returns a pointer to the read bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_textline","title":"BR_TextLine
","text":"BR_TextLine
Reads a line from the stream.
func string BR_TextLine()\n
Return value The function returns the read line.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_text","title":"BR_Text
","text":"BR_Text
Reads a string of the given length from a stream.
func string BR_Text(var int length)\n
Parameters var int length
Number of characters to read Return value
The function returns the read string.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#br_nextline","title":"BR_NextLine
","text":"BR_NextLine
Changes the read position to the next paragraph, created with BW_NextLine
func void BR_NextLine()\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#enginecalls","title":"Enginecalls","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_getlasterror","title":"WIN_GetLastError
","text":"WIN_GetLastError
Call of a Win32 API GetLastError
function
func int WIN_GetLastError()\n
Return value The function returns calling thread's last-error code.
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_createfile","title":"WIN_CreateFile
","text":"WIN_CreateFile
Call of a Win32 API CreateFileA
function
func int WIN_CreateFile(var string lpFileName,var int dwDesiredAccess,var int dwShareMode,var int lpSecurityAttributes,var int dwCreationDisposition,var int dwFlagsAndAttributes,var int hTemplateFile)\n
Parameters Full description of parameters can be found here
Return value
Information about return value can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_writefile","title":"WIN_WriteFile
","text":"WIN_WriteFile
Call of a Win32 API WriteFile
function
func void WIN_WriteFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToWrite,var int lpNumberOfBytesWritten,var int lpOverlapped)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_readfile","title":"WIN_ReadFile
","text":"WIN_ReadFile
Call of a Win32 API ReadFile
function
func void WIN_ReadFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToRead,var int lpNumberOfBytesRead,var int lpOverlapped)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_closehandle","title":"WIN_CloseHandle
","text":"WIN_CloseHandle
Call of a Win32 API CloseHandle
function
func void WIN_CloseHandle(var int hObject)\n
Parameters Full description of parameters can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#win_getfilesize","title":"WIN_GetFileSize
","text":"WIN_GetFileSize
Call of a Win32 API GetFileSize
function
func int WIN_GetFileSize(var int hFile,var int lpFileSizeHigh)\n
Parameters Full description of parameters can be found here
Return value
Information about return value can be found here
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#constants","title":"Constants","text":"In addition there are some constants defined for use with the specific engine calls.
const int CREATE_ALWAYS = 2;\nconst int OPEN_EXISTING = 3;\nconst int GENERIC_ALL = 1073741824;\nconst int GENERIC_READ = -2147483648;\nconst int FILE_SHARE_READ = 1;\nconst int FILE_SHARE_WRITE = 2;\nconst int FILE_SHARE_DELETE = 4;\nconst int FILE_ATTRIBUTE_NORMAL = 128;\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#save-and-load-variables","title":"Save and load variables","text":"const string filename = \"System\\MySave.sav\";\n\nvar string s0; // string\nvar int i1; // int\nvar int b2; // byte\nvar string c3; // char\n\nfunc void SaveMyData() \n{\n if(BW_NewFile(filename)) // Create a new file:\n { \n BW_String(s0);\n BW_Int(i1);\n BW_Byte(b2);\n BW_Char(c3); // Save stuff..\n BW_Close(); // ..and close.\n };\n};\n\nfunc void LoadMyData() {\n if(BR_OpenFile(filename)) // Try to open file:\n { \n s0 = BR_String();\n i1 = BR_Int();\n b2 = BR_Byte();\n c3 = BR_Char(); // Read in values..\n BR_Close(); // ..and close.\n }\n else \n {\n SaveMyData(); // Otherwise create a save file.\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#congratulate-the-player","title":"Congratulate the player","text":"func void Certificate(var string Username, var int Score) \n{\n var string filename; filename = ConcatStrings(Username, \"'s Certificate.txt\");\n BW_NewFile(filename); // Username + \"s Certificate.txt\". The file is then in the Gothic directory.\n BW_Text(\"Congratulations \"); BW_Text(Username);\n BW_TextLine(\"!\");\n\n BW_Text(\"You have reached \");\n BW_Text(IntToString(Score)); // Not BW_Int!\n BW_TextLine(\" Points in this fun game.\");\n\n BW_NextLine();\n\n BW_Text(\"Best regards, Author\");\n BW_Close();\n\n /*\n When calling: Certificate(\"Player\", 1000);\n a file with the name 'Player's Certificate.txt' would come out which would contain the following:\n\n Congratulations Player\n You have reached 1000 Points in this fun game.\n\n Best regards, Author\n */\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/binary_machines/#the-location-of-an-npcs","title":"The location of an NPCs","text":"func void BW_NpcPosition(var C_NPC slf) \n{\n var int ptr; ptr = MEM_Alloc(60); // 16 * 4\n MEM_CopyBytes(MEM_InstToPtr(slf) + 60, ptr, 60); // Copy slf.trafoObjToWorld\n BW_Bytes(ptr, 60); // Writes the 60 copied bytes\n MEM_Free(ptr); // And clean up..\n};\n\nfunc void BR_NpcPosition(var C_NPC slf) \n{\n var int ptr; ptr = BR_Bytes(60); // Read 60 bytes\n MEM_CopyBytes(ptr, MEM_InstToPtr(slf) + 60, 60); // Paste back into slf\n MEM_Free(ptr); // And clean up again..\n};\n\n/*\n Normal use:\n BW_NewFile(file);\n BW_NpcPosition(hero);\n BW_Close();\n*/\n
Note
Examples originally written by Gottfried and posted on World of Gothic forum.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/","title":"Draw3D","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#draw3d","title":"Draw3D","text":"Info
Dependencies: - PermMem - HookEngine Implementation: Draw3D.d on GitHub
This package allows you to draw various shapes (such as lines or bounding boxes) in three-dimensional space. This makes debugging visualizations of coordinates in the world possible.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#initialization","title":"Initialization","text":"Initialize with LeGo_Draw3D
flag.
LeGo_Init(LeGo_Draw3D);\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#line","title":"Line","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawline","title":"DrawLine
","text":"DrawLine
Creates and draws a new line and returns its handle.
func int DrawLine(var int startPosPtr, var int endPosPtr, var int color)\n
Parameters var int startPosPtr
Pointer to the float array with world coordinates of the starting point of the line var int endPosPtr
Pointer to the float array with world coordinates of the ending point of the line var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawline3","title":"DrawLine3
","text":"DrawLine3
DrawLine
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawLine3(var int x1, var int y1, var int z1,var int x2, var int y2, var int z2,var int color)\n
Parameters var int x1, y1, z1
X, Y, and Z coordinates of the starting point of the line var int x2, y2, z2
X, Y, and Z coordinates of the ending point of the line var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawlineaddr","title":"DrawLineAddr
","text":"DrawLineAddr
DrawLine
, but with the address of a line as parameter.
func int DrawLineAddr(var int linePtr, var int color)\n
Parameters var int linePtr
Pointer to the float array array with six values (startAndEndPos[6]) var int color
Color of the line as zCOLOR
Return value
The function returns a new PermMem handle to the line.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateline","title":"UpdateLine
","text":"UpdateLine
Changes the coordinates of a specific line.
func void UpdateLine(var int hndl, var int startPosPtr, var int endPosPtr)\n
Parameters var int hndl
Handle returned from DrawLine
var int startPosPtr
Pointer to an integer float array with world coordinates of the starting point of the line var int endPosPtr
Pointer to an integer float array with world coordinates of the ending point of the line "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateline3","title":"UpdateLine3
","text":"UpdateLine3
UpdateLine
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateLine3(var int hndl,var int x1, var int y1, var int z1,var int x2, var int y2, var int z2)\n
Parameters var int hndl
Handle returned from DrawLine
var int x1, y1, z1
X, Y, and Z coordinates of the starting point of the line var int x2, y2, z2
X, Y, and Z coordinates of the ending point of the line "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatelineaddr","title":"UpdateLineAddr
","text":"UpdateLineAddr
UpdateLine
, but with the address of a line as parameter.
func void UpdateLineAddr(var int hndl, var int linePtr)\n
Parameters var int hndl
Handle returned from DrawLine
var int linePtr
Pointer to an integer float array with six values (startAndEndPos[6]) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setlinecolor","title":"SetLineColor
","text":"SetLineColor
Changes the color of a specific line.
func void SetLineColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawLine
var int color
New color of the line as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseline","title":"EraseLine
","text":"EraseLine
Deletes a line from the world and the handle.
func void EraseLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#linevisible","title":"LineVisible
","text":"LineVisible
Returns whether a line is visible.
func int LineVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
Return value
The function returns TRUE
if the line is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showline","title":"ShowLine
","text":"ShowLine
Displays the line.
func void ShowLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hideline","title":"HideLine
","text":"HideLine
Hides the line.
func void HideLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#toggleline","title":"ToggleLine
","text":"ToggleLine
Changes the visibility of a line. If displayed - hide, if hidden - display.
func void ToggleLine(var int hndl)\n
Parameters var int hndl
Handle returned from DrawLine
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#sphere","title":"Sphere","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphere","title":"DrawSphere
","text":"DrawSphere
Creates and draws a new sphere (visualized as a circle) and returns its handle.
func int DrawSphere(var int centerPosPtr, var int radius, var int color)\n
Parameters var int centerPosPtr
Pointer to an integer float array with world coordinates of the sphere's center (centerPos[3]
) var int radius
Radius of the sphere as an integer float var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphere3","title":"DrawSphere3
","text":"DrawSphere3
DrawSphere
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawSphere3(var int x1, var int y1, var int z1, var int radius, var int color)\n
Parameters var int x1, y1, z1
World coordinates of the sphere's center var int radius
Radius of the sphere as an integer float var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawsphereaddr","title":"DrawSphereAddr
","text":"DrawSphereAddr
DrawSphere
, but with the address of a sphere as a parameter.
func int DrawSphereAddr(var int spherePtr, var int color)\n
Parameters var int spherePtr
Pointer to a zTBSphere3D
structure var int color
Color of the sphere as zCOLOR
Return value
The function returns a new PermMem handle to the sphere.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphere","title":"UpdateSphere
","text":"UpdateSphere
Changes the coordinates and/or size of an existing sphere.
func void UpdateSphere(var int hndl, var int centerPosPtr, var int radius)\n
Parameters var int hndl
Handle returned from DrawSphere
var int centerPosPtr
Pointer to an integer float array with world coordinates of the sphere's center (centerPos[3]
) var int radius
Radius of the sphere as an integer float "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphere3","title":"UpdateSphere3
","text":"UpdateSphere3
UpdateSphere
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateSphere3(var int hndl, var int x1, var int y1, var int z1, var int radius)\n
Parameters var int hndl
Handle returned from DrawSphere
var int x1, y1, z1
World coordinates of the sphere's center var int radius
Radius of the sphere as an integer float "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatesphereaddr","title":"UpdateSphereAddr
","text":"UpdateSphereAddr
UpdateSphere
, but with the address of a sphere as a parameter.
func void UpdateSphereAddr(var int hndl, var int spherePtr)\n
Parameters var int hndl
Handle returned from DrawSphere
var int spherePtr
Pointer to a zTBSphere3D
structure "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setspherecolor","title":"SetSphereColor
","text":"SetSphereColor
Changes the color of a specific sphere.
func void SetSphereColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawSphere
var int color
New color of the sphere as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#erasesphere","title":"EraseSphere
","text":"EraseSphere
Deletes a sphere from the world and its handle.
func void EraseSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#spherevisible","title":"SphereVisible
","text":"SphereVisible
Returns whether a sphere is visible.
func int SphereVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
Return value
The function returns TRUE
if the sphere is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showsphere","title":"ShowSphere
","text":"ShowSphere
Displays the sphere.
func void ShowSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hidesphere","title":"HideSphere
","text":"HideSphere
Hides the sphere.
func void HideSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#togglesphere","title":"ToggleSphere
","text":"ToggleSphere
Changes the visibility of a sphere. If displayed - hide, if hidden - display.
func void ToggleSphere(var int hndl)\n
Parameters var int hndl
Handle returned from DrawSphere
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#bounding-box","title":"Bounding Box","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbbox","title":"DrawBBox
","text":"DrawBBox
Creates and draws a new bounding box and returns its handle.
func int DrawBBox(var int startPosPtr, var int endPosPtr, var int color)\n
Parameters var int startPosPtr
Pointer to an integer float array with world coordinates of the bounding box's first point (startPos[3]
) var int endPosPtr
Pointer to an integer float array with world coordinates of the bounding box's second point (endPos[3]
) var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbbox3","title":"DrawBBox3
","text":"DrawBBox3
DrawBBox
, but with world coordinates as parameters, instead of zVEC3
pointers.
func int DrawBBox3(var int x1, var int y1, var int z1, var int x2, var int y2, var int z2, var int color)\n
Parameters var int x1, y1, z1
World coordinates of the bounding box's first point var int x2, y2, z2
World coordinates of the bounding box's second point var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawbboxaddr","title":"DrawBBoxAddr
","text":"DrawBBoxAddr
DrawBBox
, but with the address of a bounding box as a parameter.
func int DrawBBoxAddr(var int bboxPtr, var int color)\n
Parameters var int bboxPtr
Pointer to an integer float array with six values (startAndEndPos[6]) var int color
Color of the bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebbox","title":"UpdateBBox
","text":"UpdateBBox
Changes the coordinates of an existing bounding box.
func void UpdateBBox(var int hndl, var int startPosPtr, var int endPosPtr)\n
Parameters var int hndl
Handle returned from DrawBBox
var int startPosPtr
Pointer to an integer float array with world coordinates of the bounding box's first point (startPos[3]
) var int endPosPtr
Pointer to an integer float array with world coordinates of the bounding box's second point (endPos[3]
) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebbox3","title":"UpdateBBox3
","text":"UpdateBBox3
UpdateBBox
, but with world coordinates as parameters, instead of zVEC3
pointers.
func void UpdateBBox3(var int hndl, var int x1, var int y1, var int z1, var int x2, var int y2, var int z2)\n
Parameters var int hndl
Handle returned from DrawBBox
var int x1, y1, z1
World coordinates of the bounding box's first point var int x2, y2, z2
World coordinates of the bounding box's second point "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updatebboxaddr","title":"UpdateBBoxAddr
","text":"UpdateBBoxAddr
UpdateBBox
, but with the address of a bounding box as a parameter.
func void UpdateBBoxAddr(var int hndl, var int bboxPtr)\n
Parameters var int hndl
Handle returned from DrawBBox
var int bboxPtr
Pointer to an integer float array with six values (startAndEndPos[6]) "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setbboxcolor","title":"SetBBoxColor
","text":"SetBBoxColor
Changes the color of a specific bounding box.
func void SetBBoxColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawBBox
var int color
New color of the bounding box as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#erasebbox","title":"EraseBBox
","text":"EraseBBox
Deletes a bounding box from the world and its handle.
func void EraseBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#bboxvisible","title":"BBoxVisible
","text":"BBoxVisible
Returns whether a bounding box is visible.
func int BBoxVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
Return value
The function returns TRUE
if the bounding box is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showbbox","title":"ShowBBox
","text":"ShowBBox
Displays the bounding box.
func void ShowBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hidebbox","title":"HideBBox
","text":"HideBBox
Hides the bounding box.
func void HideBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#togglebbox","title":"ToggleBBox
","text":"ToggleBBox
Changes the visibility of a bounding box. If displayed - hide, if hidden - display.
func void ToggleBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawBBox
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#oriented-bounding-box","title":"Oriented Bounding Box","text":""},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#drawobboxaddr","title":"DrawOBBoxAddr
","text":"DrawOBBoxAddr
Creates and draws a new oriented bounding box based on the address of an oriented bounding box and returns its handle.
func int DrawOBBoxAddr(var int oBBoxPtr, var int color)\n
Parameters var int oBBoxPtr
Pointer to a zCOBBox3D
structure var int color
Color of the oriented bounding box as zCOLOR
Return value
The function returns a new PermMem handle to the oriented bounding box.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#updateobboxaddr","title":"UpdateOBBoxAddr
","text":"UpdateOBBoxAddr
Changes the coordinates and orientation of an existing oriented bounding box.
func void UpdateOBBoxAddr(var int hndl, var int oBBoxPtr)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
var int oBBoxPtr
Pointer to a zCOBBox3D
structure "},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#setobboxcolor","title":"SetOBBoxColor
","text":"SetOBBoxColor
Changes the color of a specific oriented bounding box.
func void SetOBBoxColor(var int hndl, var int color)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
var int color
New color of the oriented bounding box as zCOLOR
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseobbox","title":"EraseOBBox
","text":"EraseOBBox
Deletes an oriented bounding box from the world and its handle.
func void EraseOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#obboxvisible","title":"OBBoxVisible
","text":"OBBoxVisible
Returns whether an oriented bounding box is visible.
func int OBBoxVisible(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
Return value
The function returns TRUE
if the oriented bounding box is visible/displayed. FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#showobbox","title":"ShowOBBox
","text":"ShowOBBox
Displays the oriented bounding box.
func void ShowOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#hideobbox","title":"HideOBBox
","text":"HideOBBox
Hides the oriented bounding box.
func void HideOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#toggleobbox","title":"ToggleOBBox
","text":"ToggleOBBox
Changes the visibility of an oriented bounding box. If displayed - hide, if hidden - display.
func void ToggleOBBox(var int hndl)\n
Parameters var int hndl
Handle returned from DrawOBBoxAddr
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#eraseall","title":"EraseAll
","text":"EraseAll
Deletes all draw elements and their handles from the world.
func void EraseAll()\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#examples","title":"Examples","text":"World coordinates are not particularly informative. This package aims to help and allows visualizing world coordinates in the form of lines, spheres (as circles), bounding boxes, and oriented bounding boxes in three-dimensional space.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#visualizing-straight-line-to-an-npc","title":"Visualizing Straight Line to an NPC","text":"To draw a line between two NPCs, you only need the coordinates of the two NPCs.
func void Example_1() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var int point1[3];\n point1[0] = her.trafoObjToWorld[3];\n point1[1] = her.trafoObjToWorld[7];\n point1[2] = her.trafoObjToWorld[11];\n\n var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);\n var int point2[3];\n point2[0] = oth.trafoObjToWorld[3];\n point2[1] = oth.trafoObjToWorld[7];\n point2[2] = oth.trafoObjToWorld[11];\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawLine(_@(point1), _@(point2), zCOLOR_GREEN);\n } else {\n UpdateLine(hndl, _@(point1), _@(point2));\n };\n};\n
This function can now be called continuously using FrameFunction
to continuously adjust the straight line according to the positions of the characters.
FF_Apply(Example_1);\n
Alternatively, you can write the function as follows:
func void Example_1() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawLine3(her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],\n oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11],\n zCOLOR_GREEN);\n } else {\n UpdateLine3(hndl, her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],\n oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11]);\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#visualizing-a-distance-of-5-meters","title":"Visualizing a Distance of 5 Meters","text":"It becomes more interesting when dealing with \"abstract\" coordinates. For instance, you can visualize a \"safety distance\" around the player using a bounding box or a sphere, to check AI reactions at certain distances.
//*******************\n// Bounding Box\n//*******************\nfunc void Example_2() {\n var zCVob her; her = Hlp_GetNpc(hero);\n\n // Safety distance around the player (5 meters)\n var int distance; distance = mkf(500);\n\n // Lower corner of the bounding box\n var int point1[3];\n point1[0] = subf(her.trafoObjToWorld[3], distance);\n point1[1] = subf(her.trafoObjToWorld[7], distance);\n point1[2] = subf(her.trafoObjToWorld[11], distance);\n\n // Upper corner of the bounding box (diagonally opposite)\n var int point2[3];\n point2[0] = addf(her.trafoObjToWorld[3], distance);\n point2[1] = addf(her.trafoObjToWorld[7], distance);\n point2[2] = addf(her.trafoObjToWorld[11], distance);\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawBBox(_@(point1), _@(point2), zCOLOR_BLUE);\n } else {\n UpdateBBox(hndl, _@(point1), _@(point2));\n };\n};\n
To draw a sphere with a radius of 5 meters centered at a specific point, you only need the coordinates of the sphere's center.
//*******************\n// Sphere\n//*******************\nfunc void Example_2() {\n var zCVob her; her = Hlp_GetNpc(hero);\n var int centerPoint[3];\n centerPoint[0] = her.trafoObjToWorld[3];\n centerPoint[1] = her.trafoObjToWorld[7];\n centerPoint[2] = her.trafoObjToWorld[11];\n\n var int hndl;\n\n if (!Hlp_IsValidHandle(hndl)) {\n hndl = DrawSphere(_@(centerPoint), 500, zCOLOR_BLUE);\n } else {\n UpdateSphere(hndl, _@(centerPoint), 500);\n };\n};\n
Similarly, you could continuously update the bounding box/sphere using a FrameFunction
.
"},{"location":"zengin/scripts/extenders/lego/tools/draw3d/#changing-color-or-hidingdeleting-draw-elements","title":"Changing Color or Hiding/Deleting Draw Elements","text":"If you want to visualize an AI reaction, for example, you can change the color. Color values can be created using the RGBA
function based on RGB values.
func void ObserveIntruder(var int hndl, var C_NPC oth) {\n if (Npc_HasDetectedNpc(oth, hero)) {\n // Color is now red, position and size of the bounding box remain unchanged\n SetBBoxColor(hndl, zCOLOR_RED); // zCOLOR_RED == RGBA(255, 0, 0, 255)\n };\n};\n
Draw elements can also be easily hidden or completely deleted.
func void CheckDialog(var int hndl) {\n if (!InfoManager_HasFinished()) {\n // Hide bounding box during dialogs\n HideBBox(hndl);\n\n // EraseBBox(hndl); // Or delete including the handle\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/","title":"EventHandler","text":""},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventhandler","title":"EventHandler","text":"Info
Dependencies: - PermMem Implementation: EventHandler.d on GitHub
This package allows to create new events and trigger them at desired times. The Gamestate package already uses it.
Warning
The EventHandler requires some basic understanding of the PermMem. The documentation can be found here.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#initialization","title":"Initialization","text":"Initialize with LeGo_EventHandler
flag.
LeGo_Init(LeGo_EventHandler);\n
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_create","title":"Event_Create
","text":"Event_Create
Creates a new event and returns a handle to it.
func int Event_Create()\n
Return value The function returns a new PermMem handle to an event.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_delete","title":"Event_Delete
","text":"Event_Delete
Alias to PermMem delete
. Cleans up the handle.
func void Event_Delete(var int event)\n
Parameters var int event
Handle returned from Event_Create
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_empty","title":"Event_Empty
","text":"Event_Empty
Checks whether the event is \"empty\", i.e. nothing will happen after its execution.
func int Event_Empty(var int event)\n
Parameters var int event
Handle returned from Event_Create
Return value
The function returns TRUE
if event is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_has","title":"Event_Has
","text":"Event_Has
Checks if function
is added to the event.
func int Event_Has(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_add","title":"Event_Add
","text":"Event_Add
Adds an event handler function. The handler is called after running Event_Execute
.
func void Event_Add(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_addonce","title":"Event_AddOnce
","text":"Event_AddOnce
Event_Add
but checks if the handler function is already added, to prevent duplicates.
func void Event_AddOnce(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_remove","title":"Event_Remove
","text":"Event_Remove
Removes the event handler function
from the event.
func void Event_Remove(var int event, var func function)\n
Parameters var int event
Handle returned from Event_Create
var func function
Function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#event_execute","title":"Event_Execute
","text":"Event_Execute
Core of the package. Calls all functions registered via Event_Add
and Event_AddOnce
.
func void Event_Execute(var int event, var int data)\n
Parameters var int event
Handle returned from Event_Create
var int data
Int parameter passed to all executed functions "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#ptr-functions","title":"Ptr functions","text":"Tip
The pointer functions are used internally by the previous functions. If you created an event with Event_Create
use functions without Ptr
in the name, but if you created event with EventPtr_Create
use only Ptr
functions. The normal user will probably never need the pointer versions, however the choice, which one to use is yours.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_create","title":"EventPtr_Create
","text":"EventPtr_Create
Creates a new event and returns a pointer to it.
func int EventPtr_Create()\n
Return value The function returns a new PermMem pointer to an event.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_delete","title":"EventPtr_Delete
","text":"EventPtr_Delete
Alias to PermMem free
. Cleans up the pointer.
func void EventPtr_Delete(var int eventPtr)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_empty","title":"EventPtr_Empty
","text":"EventPtr_Empty
Checks whether the event is \"empty\", i.e. nothing will happen after its execution.
func int EventPtr_Empty(var int eventPtr)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
Return value
The function returns TRUE
if empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_has","title":"EventPtr_Has
","text":"EventPtr_Has
Checks if function
is added to an event.
func int EventPtr_Has(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_hasi","title":"EventPtr_HasI
","text":"EventPtr_HasI
EventPtr_Has
but with function ID instead of pointer. Used mainly internally.
func int EventPtr_HasI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of checked function Return value
The function returns TRUE
if function is added, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_add","title":"EventPtr_Add
","text":"EventPtr_Add
Adds an event handler function. The handler is called after running EventPtr_Execute
.
func void EventPtr_Add(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addi","title":"EventPtr_AddI
","text":"EventPtr_AddI
EventPtr_Add
but with function ID instead of pointer. Used mainly internally.
func void EventPtr_AddI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addonce","title":"EventPtr_AddOnce
","text":"EventPtr_AddOnce
Event_Add
but checks if function is already added, to prevent duplicates.
func void EventPtr_AddOnce(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_addoncei","title":"EventPtr_AddOnceI
","text":"EventPtr_AddOnceI
EventPtr_AddI
but checks if function is already added, to prevent duplicates.
func void EventPtr_AddOnceI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be added "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_remove","title":"EventPtr_Remove
","text":"EventPtr_Remove
Removes a function from the event's call list.
func void EventPtr_Remove(var int eventPtr, var func function)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var func function
Function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_removei","title":"EventPtr_RemoveI
","text":"EventPtr_RemoveI
EventPtr_Remove
but with function ID instead of pointer. Used mainly internally.
func void EventPtr_RemoveI(var int eventPtr, var int id)\n
Parameters var int eventPtr
Pointer returned from EventPtr_Create
var int id
ID of function to be removed "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#eventptr_execute","title":"EventPtr_Execute
","text":"EventPtr_Execute
Core of the package. Calls all functions registered via EventPtr_Add
and EventPtr_AddOnce
.
func void EventPtr_Execute(var int eventPtr, var int data)\n
var int eventPtr
Pointer returned from EventPtr_Create
var int data
Int parameter passed to all executed functions "},{"location":"zengin/scripts/extenders/lego/tools/event_handler/#examples","title":"Examples","text":"Note
This article has no built-in examples, but the best way to understand how EventHandler works is reading source code of the Gamestate package.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/","title":"FrameFunctions","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#framefunctions","title":"FrameFunctions","text":"Info
Dependencies: - Floats - PermMem - HookEngine - Timer Implementation: FrameFunctions.d on GitHub
The FrameFunctions package allows to call any number of functions called on every frame, or every specified time delay.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#initialization","title":"Initialization","text":"Initialize with LeGo_FrameFunctions
flag.
LeGo_Init(LeGo_FrameFunctions);\n
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_apply","title":"FF_Apply
","text":"FF_Apply
Adds the Daedalus function function
to the running FrameFunctions list. function
is called each frame.
func void FF_Apply(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applygt","title":"FF_ApplyGT
","text":"FF_ApplyGT
Adds the Daedalus function function
to the running FrameFunctions list. function
is called every frame except when the game is paused.
func void FF_ApplyGT(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applydata","title":"FF_ApplyData
","text":"FF_ApplyData
Adds the Daedalus function function
to the running FrameFunctions list. The integer parameter data
is passed to the function function
.
func void FF_ApplyData(var func function, var int data)\n
Parameters var func function
Name of the function. var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyext","title":"FF_ApplyExt
","text":"FF_ApplyExt
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times.
func void FF_ApplyExt(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextgt","title":"FF_ApplyExtGT
","text":"FF_ApplyExtGT
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. Gets called only when the game is not paused.
func void FF_ApplyExtGT(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextdata","title":"FF_ApplyExtData
","text":"FF_ApplyExtData
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. The integer parameter data
is passed to the function function
.
func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function. var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyextdatagt","title":"FF_ApplyExtDataGT
","text":"FF_ApplyExtDataGT
Adds the Daedalus function function
to the running FrameFunctions list. The function function
is called every delay
milliseconds, and it runs only cycles
number of times. The integer parameter data
is passed to the function function
. Gets called only when the game is not paused.
func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function. var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonce","title":"FF_ApplyOnce
","text":"FF_ApplyOnce
Alias to FF_Apply, which only adds the function once, even after multiple calls.
func void FF_ApplyOnce(var func function)\n
Parameters var func function
Name of the function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyoncegt","title":"FF_ApplyOnceGT
","text":"FF_ApplyOnceGT
Alias to FF_ApplyGT, which only adds the function once, even after multiple calls. Loop doesn't run if the game is paused.
func voidoften FF_ApplyOnceGT(var func function)\n
Parameters var func function
Name of the function. "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyoncedata","title":"FF_ApplyOnceData
","text":"FF_ApplyOnceData
Alias to FF_ApplyData, which only adds the function with the specified parameter once, even after multiple calls.
func void FF_ApplyOnceData(var func function, var int data)\n
Parameters var func function
Name of the function. var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceext","title":"FF_ApplyOnceExt
","text":"FF_ApplyOnceExt
Alias to FF_ApplyExt, which adds the function only once, after repeated calls.
func void FF_ApplyOnceExt(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceextgt","title":"FF_ApplyOnceExtGT
","text":"FF_ApplyOnceExtGT
Alias to FF_ApplyExtGT, which adds the function only once after repeated calls. Loop doesn't run if the game is paused.
func void FF_ApplyOnceExtGT(var func function, var int delay, var int cycles)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_applyonceextdata","title":"FF_ApplyOnceExtData
","text":"FF_ApplyOnceExtData
Alias to FF_ApplyExtData, which adds the function with the specified parameter only once, after repeated calls.
func void FF_ApplyOnceExtData(var func function, var int delay, var int cycles, var int data)\n
Parameters var func function
Name of the function var int delay
Delay between calls in milliseconds (0 = every frame) var int cycles
How many times should the function be called (-1 = endless) var int data
Value passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_active","title":"FF_Active
","text":"FF_Active
Checks whether the function
is active.
func int FF_Active(var func function)\n
Parameters var func function
Name of the function Return value The function returns TRUE
if the function is active, FALSE
if it is not.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_activedata","title":"FF_ActiveData
","text":"FF_ActiveData
Checks whether the function
with the specified data
is active.
func int FF_ActiveData(var func function, var int data)\n
Parameters var func function
Name of the function var int data
Value previously passed to the function Return value The function returns TRUE
if the function is active, FALSE
if it is not.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_remove","title":"FF_Remove
","text":"FF_Remove
Stops a specific FrameFunction.
func void FF_Remove(var func function)\n
Parameters var func function
Name of the stopped function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_removeall","title":"FF_RemoveAll
","text":"FF_RemoveAll
Stops all intsnces of a specific FrameFunction.
func void FF_RemoveAll(var func function)\n
Parameters var func function
Name of the stopped function "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#ff_removedata","title":"FF_RemoveData
","text":"FF_RemoveData
Stops a specific FrameFunction, with the specified value (see FF_ApplyExtData
).
func void FF_RemoveData(var func function, var int data)\n
Parameters var func function
Name of the stopped function var int data
Value previously passed to the function as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#a-function-called-every-frame","title":"A function called every frame","text":"In this example function MyFunc
will be executed on every frame.
func void Example1()\n{\n FF_Apply(MyFunc);\n};\n\nfunc void MyFunc() {};\n
After the Example1
function is executed the function MyFunc
is called on every frame. The easiest and best way to run a function from the beginning is to call FF-Apply
directly in the Init_Global
(under LeGo_Init
), there is a small problem: If the game is loaded, Init_Global
is called a second time, the function is added to the list again and is therefore always called twice.
To avoid this effect, you should check whether the function is already active:
func void Example1()\n{\n if(!FF_Active(MyFunc))\n {\n FF_Apply(MyFunc);\n };\n};\n
However, since LeGo version 2.2 there is an even more pleasant method to do this:
func void Example1()\n{\n FF_ApplyOnce(MyFunc);\n};\n
FF_ApplyOnce
function already implements the check for function activity."},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#calling-delayed-function","title":"Calling delayed function","text":"Create a function, that is called once after 3 seconds.
func void Example2()\n{\n FF_ApplyExt(MyFunc2, 3000, 1); // 3000 ms = 3 s, this function is called only once\n};\n\nfunc void MyFunc2() {};\n
There is also a Once
variant of this function, that prevents adding it twice into the frame function list.
func void Example2()\n{\n FF_ApplyOnceExt(MyFunc2, 3000, 1);\n};\n
Note
FF_ApplyExt(MyFunc, 0, -1)
is the same as FF_Apply(MyFunc)
.
"},{"location":"zengin/scripts/extenders/lego/tools/frame_functions/#framefunction-with-timer","title":"FrameFunction with Timer","text":"Since LeGo 2.2, FrameFunctions package uses the Timer package, so it is possible to pause FrameFunctions at will:
func void Example3()\n{\n FF_ApplyOnceExt(MyFunc3, 4000, 2);\n};\n\nfunc void MyFunc3()\n{\n Timer_SetPaused(!Timer_GetPaused());\n};\n
This would pause the timer after 4 seconds and let it continue after 8 seconds. Warning
Because the timer doesn't run, the frame function execution is stopped as well. This script won't work. If the timer is to be paused, it must be paused outside FrameFunctions.
Note
This is translation of article originally written by Gottfried and Lehona and hosted on LeGo's official documentation website.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/","title":"Hashtables","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#hashtables","title":"Hashtables","text":"Info
Dependencies: - PermMem Implementation: Hashtable.d on GitHub
Hashtables package is an implementation of hashtables in Gothic. Currently (version 2.8.0) only integers are supported as keys. The Hashtables grow automatically.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_createsized","title":"HT_CreateSized
","text":"HT_CreateSized
Generates a hashtable of the specified size.
func int HT_CreateSized(var int size)\n
Parameters var int size
Size of the hashtable to be created Return value
The function returns a handle to the created hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_create","title":"HT_Create
","text":"HT_Create
Generates a standard size hashtable.
func int HT_Create()\n
Return value The function returns a handle to the created hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_insert","title":"HT_Insert
","text":"HT_Insert
Inserts a value into the Hashtable.
func void HT_Insert(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The value to be inserted var int key
The key associated with the value "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_resize","title":"HT_Resize
","text":"HT_Resize
Changes the size of the hashtable (usually not necessary as it happens automatically).
func void HT_Resize(var int handle, var int size)\n
Parameters var int handle
Handle of a hashtable var int size
The new size of the hashtable "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_get","title":"HT_Get
","text":"HT_Get
Reads a value from the hashtable.
func int HT_Get(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key whose value is to be read Return value
The function returns the value associated with the key.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_has","title":"HT_Has
","text":"HT_Has
Checks if the key already exist in hashtable.
func int HT_Has(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key to be checked Return value The function returns TRUE
if the key exist, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_remove","title":"HT_Remove
","text":"HT_Remove
Removes a key from the hashtable.
func void HT_Remove(var int handle, var int key)\n
Parameters var int handle
Handle of a hashtable var int key
The key to be removed "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_change","title":"HT_Change
","text":"HT_Change
Changes the value of a key already existing in the hashtable.
func void HT_Change(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The new value var int key
The key whose value is to be changed "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_insertorchange","title":"HT_InsertOrChange
","text":"HT_InsertOrChange
Inserts a value into the Hashtable, or changes the value if the key already exist into hashtable.
func void HT_InsertOrChange(var int handle, var int val, var int key)\n
Parameters var int handle
Handle of a hashtable var int val
The new value var int key
The key whose value is to be changed or associated with the value. "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_getnumber","title":"HT_GetNumber
","text":"HT_GetNumber
Returns the number of entries in a hashtable.
func int HT_GetNumber(var int handle)\n
Parameters var int handle
Handle of a hashtable Return value
The function returns the number of entries in the hashtable.
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_foreach","title":"HT_ForEach
","text":"HT_ForEach
Performs a function for each value pair in the hashtable.
func void HT_ForEach(var int handle, var func fnc)\n
Parameters var int handle
Handle of a hashtable var func fnc
A function with signature void (int key, int val)
"},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#ht_destroy","title":"HT_Destroy
","text":"HT_Destroy
Deletes the hashtable.
func void HT_Destroy(var int handle)\n
Parameters var int handle
The handle of the hashtable to be deleted "},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/hashtables/#simple-operations","title":"Simple operations","text":"func void PrintKeyValuePair(var int key, var int val)\n{\n Print(ConcatStrings(ConcatStrings(\"Key: \", IntToString(key)), ConcatStrings(\", Value: \", IntToString(val))));\n};\n\nfunc void example()\n{\n // Create a new hashtable\n var int hashtableHandle; hashtableHandle = HT_Create();\n\n // Insert values into the hashtable\n HT_Insert(hashtableHandle, 42, 1);\n HT_Insert(hashtableHandle, 23, 2);\n HT_Insert(hashtableHandle, 56, 3);\n\n // Get a value from the hashtable\n var int value; value = HT_Get(hashtableHandle, 2);\n Print(ConcatStrings(\"Value associated with key 2: \", IntToString(value)));\n\n // Check if a key exists in the hashtable\n if (HT_Has(hashtableHandle, 3))\n {\n Print(\"Key 3 exists in the hashtable.\");\n }\n else\n {\n Print(\"Key 3 does not exist in the hashtable.\");\n };\n\n // Remove a key from the hashtable\n HT_Remove(hashtableHandle, 1);\n\n // Change the value associated with a key\n HT_Change(hashtableHandle, 99, 3);\n\n // Insert a value or change it if the key exists\n HT_InsertOrChange(hashtableHandle, 123, 4);\n\n // Get the number of entries in the hashtable\n var int numEntries; numEntries = HT_GetNumber(hashtableHandle);\n Print(ConcatStrings(\"Number of entries in the hashtable: \", IntToString(numEntries)));\n\n\n // Iterate through the hashtable and print key-value pairs\n // Function from top of the example is used here\n HT_ForEach(hashtableHandle, PrintKeyValuePair);\n\n // Destroy the hashtable\n HT_Destroy(hashtableHandle);\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/","title":"HookDaedalus","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalus","title":"HookDaedalus","text":"Info
Dependencies: - None Implementation: HookDaedalus.d on GitHub
This package allows hooking daedalus functions. The principle is similar HookEngine. We have a function (hooked function) into which we would like to hook another function (hook function).
Tip
Having to hook a Daedalus function should be pretty rare, because you can simply adjust the corresponding function. However, it may become necessary in some contexts.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfunc","title":"HookDaedalusFunc
","text":"HookDaedalusFunc
Hooks the function.
func void HookDaedalusFunc(var func hooked, var func hook)\n
Parameters var func hooked
Hooked function var func hook
Hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfuncf","title":"HookDaedalusFuncF
","text":"HookDaedalusFuncF
Alias to the HookDaedalusFunc
function.
func void HookDaedalusFuncF(var func hooked, var func hook)\n
Parameters var func hooked
Hooked function var func hook
Hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfunci","title":"HookDaedalusFuncI
","text":"HookDaedalusFuncI
HookDaedalusFunc
but with function ID.
func void HookDaedalusFuncI(var int hookedID, var int hookID)\n
Parameters var int hookedID
ID of hooked function var int hookID
ID of hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hookdaedalusfuncs","title":"HookDaedalusFuncS
","text":"HookDaedalusFuncS
HookDaedalusFunc
but with function name.
func void HookDaedalusFuncS(var string hookedName, var string hookName)\n
Parameters var string hookedName
Name of hooked function var string hookName
Name of hook function "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#ishookd","title":"IsHookD
","text":"IsHookD
Checks whether a function is already hooking another. Each function can be hooked any number of times, but each function can only hook one other.
func int IsHookD(var int funcID)\n
Parameters var int funcID
Symbol index of a hook function Return value
The function returns TRUE
if the function is already hooking another, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#continuecall","title":"ContinueCall
","text":"ContinueCall
Continues the program run with the original function.
func void ContinueCall()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passargumenti","title":"PassArgumentI
","text":"PassArgumentI
Passes an integer as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentI(var int i)\n
Parameters var int i
Integer argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passarguments","title":"PassArgumentS
","text":"PassArgumentS
Passes a string as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentS(var string s)\n
Parameters var string s
String argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#passargumentn","title":"PassArgumentN
","text":"PassArgumentN
Passes an instance as an argument to the original function. Must be called before ContinueCall
.
func void PassArgumentN(var instance n)\n
Parameters var instance n
Instance argument to forward "},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hook-before-function","title":"Hook before function","text":"We have a hook:
HookDaedalusFunc(hooked, hook);\n
The functions can look like that: func void hooked() \n{\n Print(\"Original function\");\n};\n\nfunc void hook() \n{\n Print(\"Our hook\");\n ContinueCall();\n};\n
The results should look like that Our hook\nOriginal function\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#hook-after-function","title":"Hook after function","text":"We have the same hook:
HookDaedalusFunc(hooked, hook);\n
The functions are also similar, but the ContinueCall();
is called first: func void hooked() \n{\n Print(\"Original function\");\n};\n\nfunc void hook() \n{\n ContinueCall();\n Print(\"Our hook\");\n};\n
The results should look like that: Original function\nOur hook\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#arguments-and-return-values","title":"Arguments and return values","text":"If a function to be hooked expects parameters or returns a value, our hooking function should conform to that.
func int hooked(var int i) \n{\n Print(\"Original function\");\n return i+1;\n};\n\nfunc int hook(var int i) \n{\n Print(\"Our hook\");\n PassArgumentI(i);\n ContinueCall();\n};\n
In this case, we may not return the value at the end of the hook because the returned value will just stay on the stack. However, we shouldn't give up on calling PassArgumentI(i)
to ensure that it is still on top of the stack when the program continues with hooked."},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#manipulation-of-arguments-and-return-values","title":"Manipulation of arguments and return values","text":"We can also manipulate arguments and return values with our hook.
func int hook(var int i) \n{\n Print(\"Our hook\");\n PassArgumentI(i+1); // add 1\n ContinueCall();\n i = MEM_PopIntResult();\n i *= 2; // Multiply by 2\n return i;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_dae/#multiple-hooks","title":"Multiple hooks","text":"A function can be hooked any number of times, but each function can only hook one. New hooks are always inserted after the previous one. The following example illustrates this quite well.
HookDaedalusFunc(a, b); // B hooks A\nHookDaedalusFunc(a, c); // C hooks A to B\nHookDaedalusFunc(a, d); // D hooks A to C\n\nHookDaedalusFunc(c, b); // Ignored because B is already hooking a function\n\nvar int i; i = a(1);\n\n\n// Hooked function\nfunc int a(var int i) \n{\n MEM_Info(ConcatStrings(\"--- A: \", IntToString(i)));\n return i+1;\n};\n\n// First hook function:\n// Replaces `a` because the program run is not continued with ContinueCall\nfunc int b(var int i) \n{\n MEM_Info(ConcatStrings(\" -- B: \", IntToString(i)));\n return i;\n};\n\n// Second hook function:\n// Increments the argument before ContinueCall and then decrements the return value\nfunc int c(var int i) \n{\n MEM_Info(ConcatStrings(\" -> C: \", IntToString(i)));\n passArgumentI(i+1);\n ContinueCall();\n\n i = MEM_PopIntResult();\n i -= 1;\n MEM_Info(ConcatStrings(\" <- C: \", IntToString(i)));\n return i;\n};\n\n// Third hook function:\n// Increments the argument before ContinueCall and then decrements the return value\nfunc int d(var int i) \n{\n MEM_Info(ConcatStrings(\"-> D: \", IntToString(i)));\n passArgumentI(i+1);\n ContinueCall();\n\n i = MEM_PopIntResult();\n i -= 1;\n MEM_Info(ConcatStrings(\"<- D: \", IntToString(i)));\n return i;\n};\n\n// Output:\n// -> D: 1\n// -> C: 2\n// -- B: 3\n// <- C: 2\n// <- D: 1\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/","title":"HookEngine","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengine","title":"HookEngine","text":"Info
Dependencies: - None Implementation: HookEngine.d on GitHub
This package allows you to hook anywhere in an engine function to run your own Daedalus code.
Tip
Zerxes has provided a list of all engine functions for G2, including the number of bytes to fill in for oldInstr
. This list can be found here. This should make it possible for everyone to use the HookEngine effectively without IDA.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengine_1","title":"HookEngine
","text":"HookEngine
Attaches a function to an engine function address.
func void HookEngine(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookengines","title":"HookEngineS
","text":"HookEngineS
Alias to the HookEngine
function.
func void HookEngineS(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookenginei","title":"HookEngineI
","text":"HookEngineI
Alias to HookEngine
with funcID.
func void HookEngineI(var int address, var int oldInstr, var int funcID)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var int funcID
ID of Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hookenginef","title":"HookEngineF
","text":"HookEngineF
Alias to HookEngine
with func
parameter.
func void HookEngineF(var int address, var int oldInstr, var func function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var func function
Daedalus function to be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishooked","title":"IsHooked
","text":"IsHooked
Checks if a hook is already present at a given address.
func var int IsHooked(var int address)\n
Parameters var int address
Address of an engine function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishook","title":"IsHook
","text":"IsHook
Checks if a hook with a certain function is already present at an address.
func var int IsHook(var int address, var string function)\n
Parameters var int address
Address of an engine function. var string function
Name of a function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishooki","title":"IsHookI
","text":"IsHookI
Alias to IsHook
with a funcID as parameter.
func var int IsHookI(var int address, var int funcID)\n
Parameters var int address
Address of an engine function. var int funcID
ID of a function. Return value
The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#ishookf","title":"IsHookF
","text":"IsHookF
Alias to IsHook
with a function as parameter.
func var int IsHookF(var int address, var func function)\n
Parameters var int address
Address of an engine function. var func function
Daedalus function. Return value func
parameter The function returns TRUE
if the hook already exists at the address, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehook","title":"RemoveHook
","text":"RemoveHook
Removes a function from a hook so that it is no longer called.
func void RemoveHook(var int address, var int oldInstr, var string function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var string function
Name of Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehooki","title":"RemoveHookI
","text":"RemoveHookI
Alias to RemoveHook
with funcID.
func void RemoveHook(var int address, var int oldInstr, var int funcID)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var int funcID
ID of Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#removehookf","title":"RemoveHookF
","text":"RemoveHookF
Alias for RemoveHook
with func
parameter.
func void RemoveHook(var int address, var int oldInstr, var func function)\n
Parameters var int address
Address of an engine function to which the function should be attached. var int oldInstr
The length in bytes of the instruction to be found at address
, at least 5 bytes. Can be seen in IDA. var func function
Daedalus function that should no longer be called. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefunc","title":"ReplaceEngineFunc
","text":"ReplaceEngineFunc
Replaces an engine function with a Daedalus function.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var string replaceFunc)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var string replaceFunc
Name of a Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefunci","title":"ReplaceEngineFuncI
","text":"ReplaceEngineFuncI
Alias to ReplaceEngineFunc
with funcID.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var int funcID)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var int funcID
ID of a Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#replaceenginefuncf","title":"ReplaceEngineFuncF
","text":"ReplaceEngineFuncF
Alias to ReplaceEngineFunc
with func parameter.
func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var func function)\n
Parameters var int address
Address of the engine function to be replaced. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). var func function
Daedalus function to be called instead. "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#disableenginefunc","title":"DisableEngineFunc
","text":"DisableEngineFunc
Makes sure that an engine function is simply skipped. This is very delicate and will not always work so easily.
func void DisableEngineFunc(var int address, var int thiscall_numparams)\n
Parameters var int address
Address of the engine function to be skipped. var int thiscall_numparams
Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). "},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hook_returnfalse","title":"Hook_ReturnFalse
","text":"Hook_ReturnFalse
Simple function to replace return FALSE
in hook.
func void Hook_ReturnFalse()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#hook_returntrue","title":"Hook_ReturnTrue
","text":"Hook_ReturnTrue
Simple function to replace return TRUE
in hook.
func void Hook_ReturnTrue()\n
"},{"location":"zengin/scripts/extenders/lego/tools/hook_engine/#registers","title":"Registers","text":"In addition the HookEngine package implement x86 32-bit registers that can be used to access hooked function parameters.
var int EAX;\nvar int ECX;\nvar int EDX;\nvar int EBX;\nvar int ESP;\nvar int EBP;\nvar int ESI;\nvar int EDI; \n
"},{"location":"zengin/scripts/extenders/lego/tools/int64/","title":"Int64","text":""},{"location":"zengin/scripts/extenders/lego/tools/int64/#int64","title":"Int64","text":"Info
Dependencies: - None Implementation: Int64.d on GitHub
Int64 implements basic arithmetic for 64-bit integers based on machine code (hence the function signatures are also in machine code style). Furthermore, Int64 offers the constructor int64@
for Int64 objects, but mk64 expects a pointer, not a handle.
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/int64/#mk64","title":"mk64
","text":"mk64
Writes lo
and hi
in one place (dest). Makes Int64, hi
has to be -1
for negative 32bit lo
.
func void mk64(var int dest, var int hi, var int lo)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. var int hi
High part of integer. var int lo
Low part of integer. Examples Function looks like that:
func void mk64(var int dest, var int lo, var int hi) {\n MEM_WriteInt(dest, lo);\n MEM_WriteInt(dest+4, hi);\n };\n
So if you want to get 9876543210
low part should be set to 1286608618
and the high part to 2
var int ptr; ptr = MEM_Alloc(8);\nvar int low; low = 1286608618;\nvar int high; high = 2;\nmk64(ptr, low, high);\n// ...\nMEM_Free(ptr);\n
"},{"location":"zengin/scripts/extenders/lego/tools/int64/#neg64","title":"neg64
","text":"neg64
Negates the integer: *dest <- -(*dest)
func void neg64(var int dest)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#add64","title":"add64
","text":"add64
Adds src
to dest
: *dest <- *dest + *src
func void add64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#sub64","title":"sub64
","text":"sub64
Subtracts src
from dest
: *dest <- *dest - *src
func void sub64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#mul64","title":"mul64
","text":"mul64
Multiplies dest
by src
: *dest <- (*dest) * (*src)
func void mul64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/int64/#div64","title":"div64
","text":"div64
Divides dest
by src
: *dest <- *dest / *src
func void mul64(var int dest, var int src)\n
Parameters var int dest
A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. var int src
A pointer to an Int64 object. Will not change. "},{"location":"zengin/scripts/extenders/lego/tools/interface/","title":"Interface","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#interface","title":"Interface","text":"Info
Dependencies: - AI_Function - Anim8 - HookEngine - PermMem Implementation: Interface.d on GitHub
This package offers a lot of useful functions to work with the 2D interface.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#initialization","title":"Initialization","text":"Initialize with LeGo_Interface
and LeGo_PrintS
flag.
LeGo_Init(LeGo_Interface | LeGo_PrintS);\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#sysgettime","title":"sysGetTime
","text":"sysGetTime
Better alternative for MEM_GetSysTime()
from Ikarus.
func int sysGetTime()\n
Return value The function returns elapsed time since game (system) startup.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#rgba","title":"RGBA
","text":"RGBA
Generates a full zColor
.
func int RGBA(var int r, var int g, var int b, var int a)\n
Parameters var int r
Red channel value (0..255) var int g
Green channel value (0..255) var int b
Blue channel value (0..255) var int a
Alpha (0..255, 0 = invisible) Return value
The function returns a zColor
object.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#changealpha","title":"ChangeAlpha
","text":"ChangeAlpha
Overrides the alpha value of a given zColor
.
func int ChangeAlpha(var int zCol, var int a)\n
Parameters var int zCol
zColor
to modify var int a
New alpha value Return value
The function returns a modified zColor
object.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#getalpha","title":"GetAlpha
","text":"GetAlpha
Returns the alpha value of a given zColor
.
func int GetAlpha(var int zCol)\n
Parameters var int zCol
zColor
to get alpha from "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtext","title":"Print_CreateText
","text":"Print_CreateText
Creates a new zCViewText
on the screen with PermMem that can be freely edited.
func int Print_CreateText(var string text, var string font)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text Return value
The function returns a handle to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtextptr","title":"Print_CreateTextPtr
","text":"Print_CreateTextPtr
Print_CreateText
but returns pointer to zCViewText
instead of handle.
func int Print_CreateTextPtr(var string text, var string font)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text Return value
The function returns a pointer to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_createtextptrcolored","title":"Print_CreateTextPtrColored
","text":"Print_CreateTextPtrColored
Print_CreateTextPtr
but with additional parameter to chose color of text.
func int Print_CreateTextPtrColored(var string text, var string font, var int color)\n
Parameters var string text
The text of the zCViewText
var string font
Font of text var int color
zColor
e.g. generated with RGBA function Return value
The function returns a pointer to zCViewText
.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_gettext","title":"Print_GetText
","text":"Print_GetText
Returns zCViewText
instance from handle.
func zCViewText Print_GetText(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_gettextptr","title":"Print_GetTextPtr
","text":"Print_GetTextPtr
Returns zCViewText
pointer from handle.
func int Print_GetTextPtr(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_deletetext","title":"Print_DeleteText
","text":"Print_DeleteText
Removes a zCViewText
from the screen.
func void Print_DeleteText(var int hndl)\n
Parameters var int hndl
Handle to zCViewText
(form Print_CreateText
or Print_Ext
) "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_setalpha","title":"Print_SetAlpha
","text":"Print_SetAlpha
Changes the alpha value of a given zCViewText
.
func void Print_SetAlpha(var int hndl, var int a)\n
Parameters var int hndl
Handle to zCViewText
var int a
New alpha value "},{"location":"zengin/scripts/extenders/lego/tools/interface/#printptr_setalpha","title":"PrintPtr_SetAlpha
","text":"PrintPtr_SetAlpha
Print_SetAlpha
but with pointer to zCViewText
instead of handle.
func void PrintPtr_SetAlpha(var int ptr, var int a)\n
Parameters var int ptr
Pointer to zCViewText
var int a
New alpha value "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getscreensize","title":"Print_GetScreenSize
","text":"Print_GetScreenSize
Writes the current resolution to the Print_Screen array and the current aspect ratio to Print_Ratio variable.
func void Print_GetScreenSize()\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_screen","title":"Print_Screen
","text":"Print_Screen
An int array holding the current resolution. (Filled by Print_GetScreenSize
)
int Print_Screen[2];\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_ratio","title":"Print_Ratio
","text":"Print_Ratio
A float variable that holds the current aspect ratio. (Filled by Print_GetScreenSize
)
int Print_Ratio;\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#ps_vmax","title":"PS_VMax
","text":"PS_VMax
An int constant that holds the highest possible value of a virtual coordinate.
const int PS_VMax = 8192;\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_tovirtual","title":"Print_ToVirtual
","text":"Print_ToVirtual
Convents pixel position to a virtual position.
func int Print_ToVirtual(var int pxl, var int dim)\n
Parameters var int pxl
Pixel position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a virtual position of a given pixel position.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_tovirtualf","title":"Print_ToVirtualF
","text":"Print_ToVirtualF
Print_ToVirtual
but returns Ikarus float value instead of integer.
func int Print_ToVirtualF(var int pxl, var int dim)\n
Parameters var int pxl
Pixel position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a virtual position of a given pixel position as Ikarus float.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_topixel","title":"Print_ToPixel
","text":"Print_ToPixel
Convents virtual position to a pixel position.
func int Print_ToPixel(var int vrt, var int dim)\n
Parameters var int vrt
Virtual position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a pixel position of a given virtual position.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_topixelf","title":"Print_ToPixelF
","text":"Print_ToPixelF
Print_ToPixel
but returns Ikarus float value instead of integer.
func int Print_ToPixelF(var int vrt, var int dim)\n
Parameters var int vrt
Virtual position to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns a pixel position of a given virtual position as Ikarus float.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_toratio","title":"Print_ToRatio
","text":"Print_ToRatio
Gets the size in the specified dimension in ratioed by the screen.
func int Print_ToRatio(var int size, var int dim)\n
Parameters var int size
Size to convert var int dim
PS_X or PS_Y (see Print_Screen
) Return value
The function returns size correctly calculated to the ratio.
Example If you have a view and the view you need to be a square of 400 units, you would do:
height = Print_ToRatio(400, PS_Y);\nwidth = 400;\n
This is because width is always the max in virtual coordinates - 8192 virtual points and the height has a different height based on the ratio, this function calculates it for you. PS_X
can be used in function, if you already have the height but need the width in the correct ratio.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_toradian","title":"Print_ToRadian
","text":"Print_ToRadian
Converts angle in degrees to radians.
func int Print_ToRadian(var int angle)\n
Parameters var int angle
Angle in degrees Return value
The function returns calculated angle in radians.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_todegree","title":"Print_ToDegree
","text":"Print_ToDegree
Converts angle in radians to degrees.
func int Print_ToDegree(var int angle)\n
Parameters var int angle
Angle in radians Return value
The function returns calculated angle in degrees.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontptr","title":"Print_GetFontPtr
","text":"Print_GetFontPtr
Returns a pointer to a zCFont
by its name.
func int Print_GetFontPtr(var string font)\n
Parameters var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontname","title":"Print_GetFontName
","text":"Print_GetFontName
Returns a name of a zCFont
from its pointer.
func string Print_GetFontName(var int fontPtr)\n
Parameters var int fontPtr
Pointer to font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getstringwidth","title":"Print_GetStringWidth
","text":"Print_GetStringWidth
Returns the width of a string in pixels.
func int Print_GetStringWidth(var string s, var string font)\n
Parameters var string s
Measured string var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getstringwidthptr","title":"Print_GetStringWidthPtr
","text":"Print_GetStringWidthPtr
Print_GetStringWidth
but with zCFont
pointer instead of name.
func int Print_GetStringWidthPtr(var string s, var int font)\n
Parameters var string s
Measured string var int font
zCFont
pointer "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_getfontheight","title":"Print_GetFontHeight
","text":"Print_GetFontHeight
Returns the height of a string in pixels.
func int Print_GetFontHeight(var string font)\n
Parameters var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_ext","title":"Print_Ext
","text":"Print_Ext
Like the external PrintScreen
, writes a text on the screen, but with more options.
func int Print_Ext(var int x, var int y, var string text, var string font, var int color, var int time)\n
Parameters var int x
X coordinate on the screen (virtual) var int y
Y coordinate on the screen (virtual) var string text
Displayed text var string font
Name of font var int color
zColor
e.g. generated with RGBA function var int time
display time in milliseconds (-1 = permanent) Return value
If time == -1
, a valid handle is returned. If time != -1
, the print is only volatile and no handle is returned.
Example func void Example1()\n{\n // x, y, text, font, color, time\n Print_ExtPxl(2, 2, \"Text\", FONT_Screen, RGBA(255, 0, 0, 128), 500);\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_extpxl","title":"Print_ExtPxl
","text":"Print_ExtPxl
Print_Ext
but with pixel coordinates instead of virtual.
func int Print_ExtPxl(var int x, var int y, var string text, var string font, var int color, var int time)\n
Parameters var int x
X coordinate on the screen (pixel) var int y
Y coordinate on the screen (pixel) var string text
Displayed text var string font
Name of font var int color
zColor
e.g. generated with RGBA function var int time
display time in milliseconds (-1 = permanent) Return value
If time == -1
, a valid handle is returned. If time != -1
, the print is only volatile and no handle is returned.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestline","title":"Print_LongestLine
","text":"Print_LongestLine
Returns the longest line from text
as a string, using default line separator tilde ~
.
func string Print_LongestLine(var string text, var string font)\n
Parameters var string text
Measured text var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlineext","title":"Print_LongestLineExt
","text":"Print_LongestLineExt
Returns the longest line from text
as a string, but you specify new line separator.
func string Print_LongestLineExt(var string text, var string font, var string separator)\n
Parameters var string text
Measured text var string font
Name of font var string separator
New line separator "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlinelength","title":"Print_LongestLineLength
","text":"Print_LongestLineLength
Returns the longest line width in pixels, using default line separator tilde ~
.
func int Print_LongestLineLength(var string text, var string font)\n
Parameters var string text
Measured text var string font
Name of font "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_longestlinelengthext","title":"Print_LongestLineLengthExt
","text":"Print_LongestLineLengthExt
Returns the longest line width in pixels, but allows you to specify new line separator.
func int Print_LongestLineLengthExt(var string text, var string font, var string separator)\n
Parameters var string text
Measured text var string font
Name of font var string separator
New line separator "},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfield","title":"Print_TextField
","text":"Print_TextField
Creates a text field (view with text) using virtual coordinates.
func int Print_TextField(var int x, var int y, var string text, var string font, var int height)\n
Parameters var int x
X coordinate (virtual) var int y
Y coordinate (virtual) var string text
Text to be printed var string font
Name of font var int height
A specific line height
Return value
The function returns a text field pointer. Here is how it is used:
var zCView view; view = get(viewHndl);\nview.textLines_next = Print_TextField(x, y, text, FONT, fontHeight);\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfieldpxl","title":"Print_TextFieldPxl
","text":"Print_TextFieldPxl
Print_TextField
but with pixel coordinates.
func int Print_TextFieldPxl(var int x, var int y, var string text, var string font)\n
Parameters var int x
X coordinate (pixel) var int y
Y coordinate (pixel) var string text
Text to be printed var string font
Name of font Return value
The function returns a text field pointer. Look at the Print_TextField
return value to see an example.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#print_textfieldcolored","title":"Print_TextFieldColored
","text":"Print_TextFieldColored
Print_TextField
but you specify the color of text.
func int Print_TextFieldColored(var int x, var int y, var string text, var string font, var int height, var int color)\n
Parameters var int x
X coordinate (virtual) var int y
Y coordinate (virtual) var string text
Text to be printed var string font
Name of font var int height
A specific line height
var int color
zColor
e.g. generated with RGBA function Return value
The function returns a text field pointer. Look at the Print_TextField
return value to see an example.
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#prints","title":"PrintS
","text":"PrintS
Same function as the external Print
, but with smooth animations. The effect can be changed as desired with the user constants.
func void PrintS(var string txt)\n
Parameters var string txt
Printed text "},{"location":"zengin/scripts/extenders/lego/tools/interface/#prints_ext","title":"PrintS_Ext
","text":"PrintS_Ext
PrintS
but with an additional parameter to choose the color of the text.
func void PrintS_Ext(var string txt, var int color)\n
Parameters var string txt
Printed text var int color
zColor
e.g. generated with RGBA function "},{"location":"zengin/scripts/extenders/lego/tools/interface/#ai_prints","title":"AI_PrintS
","text":"AI_PrintS
Version of PrintS
that enqueue in given NPCs AI queue.
func void AI_PrintS(var c_npc slf, var string txt)\n
Parameters var c_npc slf
NPC to whose AI queue the function is enqueued var string txt
Printed text "},{"location":"zengin/scripts/extenders/lego/tools/interface/#ai_prints_ext","title":"AI_PrintS_Ext
","text":"AI_PrintS_Ext
Version of PrintS_Ext
that enqueue in given NPCs AI queue.
func void AI_PrintS_Ext(var c_npc slf, var string txt, var int color)\n
Parameters var c_npc slf
NPC to whose AI queue the function is enqueued var string txt
Printed text var int color
zColor
e.g. generated with RGBA function "},{"location":"zengin/scripts/extenders/lego/tools/interface/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/interface/#manage-a-print-via-zcviewtext","title":"Manage a print via zCViewText","text":"It is also possible to create the text only via Print_CreateText and set it yourself. In this example, a text should fly over the image from left to right and be deleted again. The movement is handled by Anim8:
var int MyText;\nvar int MyAnim8;\nfunc void PrintMyScrollingText(var string text) {\n MyText = Print_CreateText(text, FONT_Screen); // We create an empty text item with the font FONT_Screen\n\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Now we get the empty text item in a zCViewText\n\n MyTextObject.posx = 1; // adjust position\n MyTextObject.posy = 1; // ATTENTION: These values are virtual, i.e.: 0 = far left, 8192 = far right (i.e. no pixel specification)\n // (But if I prefer to have pixel coordinates I could use e.g. Print_ToVirtual)\n MyTextObject.timed = false; // The text should not be timed (not disappear)\n\n // Anim8 will animate a text\n // First we need a new Anim8 object:\n MyAnim8 = Anim8_New(1, false); // Start position is 1 and this value is not a float\n\n Anim8(MyAnim8, 8192, 2000, A8_Constant); // Target Position is 8192, Duration is 2000 milliseconds, and Movement Form is Constant\n\n // Now all we need is a loop that matches the x value of the text to the value of Anim8:\n FF_Apply(ScrollMyText);\n};\n\nfunc void ScrollMyText() {\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Get the text as an object again\n\n // And now compare the values:\n MyTextObject.posx = Anim8_Get(MyAnim8);\n\n // When Anim8 is done with that, we end the loop and delete the text:\n if(Anim8_Empty(MyAnim8)) {\n Print_DeleteText(MyText);\n FF_Remove(ScrollMyText);\n // The Anim8 object must of course also be deleted. We don't need it anymore.\n Anim8_Delete(MyAnim8);\n };\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/interface/#manage-a-print-via-zcviewtext-with-lego-22","title":"Manage a print via zCViewText with LeGo 2.2+","text":"In those days it was perhaps pleasant, but today it is no longer. Anim8 has seen a few improvements with LeGo 2.2 that make it much easier to create the same effect:
var int MyText;\nvar int MyAnim8;\nfunc void PrintMyScrollingText(var string text) {\n // Create and set text:\n MyText = Print_CreateText(text, FONT_Screen);\n\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText);\n\n MyTextObject.posx = 1;\n MyTextObject.posy = 1;\n\n MyTextObject.timed = false;\n\n // But now comes the trick: We use Anim8_NewExt, this allows us to set a \"Handler\" and \"Data\".\n MyAnim8 = Anim8_NewExt(1, ScrollMyText, MyText, false);\n\n // ScrollMyText is passed as the handler and MyText as the data.\n // In concrete terms, this means: ScrollMyText is always called\n // when Anim8 has recalculated the position.\n // Pass data and the new position as parameters. Let's see how it goes.\n\n // Set the animation again as usual:\n Anim8(MyAnim8, 8192, 2000, A8_Constant);\n\n // And this time no FrameFunction.\n // Instead, we tell Anim8 to clean up by itself when it's done:\n Anim8_RemoveIfEmpty(MyAnim8, true);\n\n // The text should also disappear by itself:\n Anim8_RemoveDataIfEmpty(MyAnim8, true);\n\n // Since MyText is a handle, this will work.\n // If MyText were a pointer, RemoveDataIfEmpty should not be activated, it would lead to an error message.\n};\n\nfunc void ScrollMyText(var int MyText, var int Position) {\n // Get the text as an object again\n var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText);\n\n // And now compare the values:\n MyTextObject.posx = Position;\n\n // Since Anim8 does the deleting itself, we don't have to worry about that.\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/","title":"ItemHelper","text":""},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#itemhelper","title":"ItemHelper","text":"Info
Dependencies: - None Implementation: ItemHelper.d on GitHub
This package is very simple - it retrieves a oCItem
pointer from an C_ITEM
instance valid for the current world and session.
Warning
Make sure every world has waypoint with name TOT
(\"dead\" in German). Ikarus & LeGo need this waypoint to spawn helper NPCs. This is especially important in Gothic 1 since G1 vanilla worlds do not have the TOT
waypoint.
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/item_helper/#itm_getptr","title":"Itm_GetPtr
","text":"Itm_GetPtr
func int Itm_GetPtr(var int instance)\n
Parameters var int instance
C_ITEM
instance to get the pointer of Return value The function returns oCItem
pointer of the C_ITEM
instance.
"},{"location":"zengin/scripts/extenders/lego/tools/list/","title":"List","text":""},{"location":"zengin/scripts/extenders/lego/tools/list/#list","title":"List","text":"Info
Dependencies: - None Implementation: List.d on GitHub
The List package is a collection of functions designed to simplify the handling of zCList
and zCListSort
lists in daedalus. It offers a range of functions for creating, manipulating, and querying lists.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/list/#functions","title":"Functions","text":"Note
All functions, expect List_Compare
come with an additional \"S\" at the end for objects of type zCListSort
. (Example: List_NodeS
.) Unlike most LeGo packages, pointers are used here, not handles!
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_create","title":"List_Create
","text":"List_Create
Creates a list with an initial value.
func int List_Create(var int data)\n
Parameters var int data
The value of the first list element. Return value
The function returns a pointer to the created list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_add","title":"List_Add
","text":"List_Add
Appends a value to the end of the list.
func void List_Add(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_addfront","title":"List_AddFront
","text":"List_AddFront
Adds a value before the first element of the list.
func void List_AddFront(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_addoffset","title":"List_AddOffset
","text":"List_AddOffset
Inserts a value between two list elements.
func void List_AddOffset(var int list, var int offset, var int data)\n
Parameters var int list
The list to be used. var int offset
The number of the list element after which the value is inserted. var int data
The value to be appended. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_set","title":"List_Set
","text":"List_Set
Sets a list element to a specific value.
func void List_Set(var int node, var int data)\n
Parameters var int node
Pointer to a list element. var int data
The value to be written into the list element. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_get","title":"List_Get
","text":"List_Get
Retrieves the value of a list element.
func int List_Get(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of the list element. Return value
The function returns the value of the specified list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_node","title":"List_Node
","text":"List_Node
Returns a pointer to a list element.
func int List_Node(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of a list element. Return value
The function returns a pointer to the specified list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_length","title":"List_Length
","text":"List_Length
Returns the length of the list (number of all elements).
func int List_Length(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns the number of elements in the list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_haslength","title":"List_HasLength
","text":"List_HasLength
Checks if the list has the specified length.
func int List_HasLength(var int list, var int length)\n
Parameters var int list
The list to be used. var int length
The desired length. Return value
The function returns a boolean value indicating whether the list has the specified length or not.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_end","title":"List_End
","text":"List_End
Returns the last list element of the list.
func int List_End(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns a pointer to the last list element.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_concat","title":"List_Concat
","text":"List_Concat
Concatenates two lists.
func void List_Concat(var int list, var int list2)\n
Parameters var int list
The first list. var int list2
The second list. Its beginning is appended to the end of the first list. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_contains","title":"List_Contains
","text":"List_Contains
Returns the last list element with a specific value.
func int List_Contains(var int list, var int data)\n
Parameters var int list
The list to be used. var int data
The value to search for. Return value
The function returns the number of the last list element with the value data
.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_for","title":"List_For
","text":"List_For
Calls a function for each list element, passing a pointer to the list element as a parameter.
func void List_For(var int list, var string function)\n
Parameters var int list
The list to be used. var string function
Name of a function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_forf","title":"List_ForF
","text":"List_ForF
Similar to List_For
, but with a function parameter instead of a string.
func void ListForF(var int list, var func function)\n
Parameters var int list
The list to be used. var func function
The function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_fori","title":"List_ForI
","text":"List_ForI
Similar to List_For
, but with a function parameter instead of a string.
func void List_ForI(var int list, var int funcID)\n
Parameters var int list
The list to be used. var int funcID
ID of a function to be called for each list element (void handler(var int node)
). "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_delete","title":"List_Delete
","text":"List_Delete
Deletes a list element. All subsequent elements shift position.
func void List_Delete(var int list, var int nr)\n
Parameters var int list
The list to be used. var int nr
The number of the list element to be deleted. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_destroy","title":"List_Destroy
","text":"List_Destroy
Destroys the entire list.
func void List_Destroy(var int list)\n
Parameters var int list
The list to be destroyed. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_toarray","title":"List_ToArray
","text":"List_ToArray
Returns a pointer to a memory area containing all values of the list.
func int List_ToArray(var int list)\n
Parameters var int list
The list to be used. Return value
The function returns a memory area containing all the values of the list.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_movedown","title":"List_MoveDown
","text":"List_MoveDown
Moves the specified list node down by one position in the list.
func void List_MoveDown(var int list, var int node)\n
Parameters var int list
The list in which the node is located. var int node
The node to be moved down. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_moveup","title":"List_MoveUp
","text":"List_MoveUp
Moves the specified list node up by one position in the list.
func void List_MoveUp(var int list, var int node)\n
Parameters var int list
The list in which the node is located. var int node
The node to be moved up. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_insertsorted","title":"List_InsertSorted
","text":"List_InsertSorted
Inserts a value into a sorted list while preserving the sort order.
func void List_InsertSorted(var int list, var int data, var func compare)\n
Parameters: var int list
The list to insert the value into. var int data
The value to be inserted. var func compare
A comparison function used to determine the sort order. "},{"location":"zengin/scripts/extenders/lego/tools/list/#list_compare","title":"List_Compare
","text":"List_Compare
func int List_Compare(var int data1, var int data2, var func compare)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. var func compare
One of comparison functions. Return value The function returns the return value of specified comparison function.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#comparison-functions","title":"Comparison Functions","text":"The following comparison functions can be used as the compare
parameter in the List_InsertSorted
and List_Compare
function:
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpascending","title":"List_CmpAscending
","text":"List_CmpAscending
Compares two integer values in ascending order.
func int List_CmpAscending(var int data1, var int data2)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. Return Value:
The function returns TRUE
if data1
is greater than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpdescending","title":"List_CmpDescending
","text":"List_CmpDescending
Compares two integer values in descending order.
func int List_CmpDescending(var int data1, var int data2)\n
Parameters: var int data1
The first integer value. var int data2
The second integer value. Return Value:
The function returns TRUE
if data1
is less than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpascendingunsigned","title":"List_CmpAscendingUnsigned
","text":"List_CmpAscendingUnsigned
Compares two unsigned integer values in ascending order.
func int List_CmpAscendingUnsigned(var int data1, var int data2)\n
Parameters: var int data1
The first unsigned integer value. var int data2
The second unsigned integer value. Return Value:
The function returns TRUE
if data1
is greater than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/list/#list_cmpdescendingunsigned","title":"List_CmpDescendingUnsigned
","text":"List_CmpDescendingUnsigned
Compares two unsigned integer values in descending order.
func int List_CmpDescendingUnsigned(var int data1, var int data2)\n
Parameters: var int data1
The first unsigned integer value. var int data2
The second unsigned integer value. Return Value:
The function returns TRUE
if data1
is less than data2
, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/locals/","title":"Locals","text":""},{"location":"zengin/scripts/extenders/lego/tools/locals/#locals","title":"Locals","text":"Info
Dependencies: - StringBuilder Implementation: Locals.d on GitHub
Daedalus doesn't offer any local variables, which can quickly lead to problems with recursive functions. The Locals package allows variables to be saved temporarily on a pseudo-stack. Locals is a very specific package. People who work normally with Daedalus will probably never need it. There is also the final
function, which can be used to emulate something similar to the final
clause in Java.
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/locals/#locals_1","title":"Locals
","text":"Locals
All that has to be done to enable the Locals
is to write this function at the beginning of the function that should receive \"real\" local variables.
func void locals()\n
"},{"location":"zengin/scripts/extenders/lego/tools/locals/#final","title":"Final
","text":"Final
It is hard to explain how to use it, but very easy to understand once you've seen an example.
func int Final()\n
Example With final()
it is very easy to emulate Java's final
clause, i.e. a block of code can be specified, which is executed after this function is exited, regardless of when or where the function is exited.
func void testFinal()\n{\n if (final())\n {\n MEM_InfoBox(\"Final was called.\");\n };\n MEM_InfoBox(\"This will appear before Final\");\n};\n
Few lines of code say more than a thousand words."},{"location":"zengin/scripts/extenders/lego/tools/misc/","title":"Misc","text":""},{"location":"zengin/scripts/extenders/lego/tools/misc/#misc","title":"Misc","text":"Info
Dependencies: - Floats Implementation: Misc.d on GitHub
The Misc package introduces various helper functions that did not fit into any other package.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#constants","title":"Constants","text":"Misc package implements the phi
constant
const int phi = 1070141312; // PI/2\n
which is actually pi
divided by 2 saved as an ikarus float. Decimal: 1.5707...
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/misc/#atan2f","title":"atan2f
","text":"atan2f
Calculates the arcus tangent of an angle between the origin and (x, y) point.
func int atan2f(var int x, var int y)\n
Parameters var int x
X-coordinate var int y
Y-coordinate Return value
The function returns arcus tangent in radians as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#sin","title":"sin
","text":"sin
Calculates the sine of an angle given in radians.
func int sin(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns sine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#cos","title":"cos
","text":"cos
Calculates the cosine of an angle given in radians.
func int cos(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns cosine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#tan","title":"tan
","text":"tan
Calculates the tangent of an angle given in radians.
func int tan(var int angle)\n
Parameters var int angle
The angle in radians as a Ikarus float
Return value
The function returns tangent of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#asin","title":"asin
","text":"asin
Calculates the arcus sine.
func int asin(var int sine)\n
Parameters var int sine
The sine of an angle as a Ikarus float
Return value
The function returns arcus sine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#acos","title":"acos
","text":"acos
Calculates the arcus cosine
func int acos(var int cosine)\n
Parameters var int cosine
The cosine of an angle as a Ikarus float
Return value
The function returns arcus cosine of the angle as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#distance2d","title":"distance2D
","text":"distance2D
Calculates the distance between two points on a two-dimensional plane.
func int distance2D(var int x1, var int x2, var int y1, var int y2)\n
Parameters var int x1
X-coordinate of the first point var int x2
X-coordinate of the second point var int y1
Y-coordinate of the first point var int y2
Y-coordinate of the second point Return value
The function returns the distance between the two points.
"},{"location":"zengin/scripts/extenders/lego/tools/misc/#distance2df","title":"distance2Df
","text":"distance2Df
Calculates the distance between two points on a two-dimensional plane but parameters and return values are Ikarus floats
.
func int distance2Df(var int x1, var int x2, var int y1, var int y2)\n
Parameters var int x1
X-coordinate of the first point var int x2
X-coordinate of the second point var int y1
Y-coordinate of the first point var int y2
Y-coordinate of the second point Return value
The function returns the distance between the two points as Ikarus float
.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/","title":"PermMem","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#permmem","title":"PermMem","text":"Info
Dependencies: - Saves - Locals Implementation: PermMem.d on GitHub
PermMem is a powerful package that allows classes (or instances) to be used permanently even after loading or restarting by saving them to the ASCII .ZEN
archive in the savegame directory. PermMem manages handles that are used to access instances, and provides various functions to manipulate these handles and instances.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#new","title":"new
","text":"new
Creates a handle to a new instance of inst
.
func int new(var int inst)\n
Parameters var int inst
A valid instance. Used as \"constructor\" Return value
The function returns a new, valid PermMem handle.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#create","title":"create
","text":"create
Similar to new
, but here a pointer is returned directly and not a handle. Caution! Not managed by PermMem!
func int create(var int inst)\n
Parameters var int inst
A valid instance. Used as \"constructor\" Return value
The function returns a pointer to the new instance.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#wrap","title":"wrap
","text":"wrap
\"Wraps\" a handle \"around\" a pointer so that the pointer can be used with any function that expects handles. Only conditionally managed by PermMem.
func int wrap(var int inst, var int ptr)\n
Parameters var int inst
A valid instance. Determines the type of the handle var int ptr
Pointer to wrap Return value
The function returns a handle with ptr
as content.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#clear","title":"clear
","text":"clear
Cleans the handle. After that it is invalid.
func void clear(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#release","title":"release
","text":"release
Frees the handle. The reserved memory is not deleted, the handle becomes invalid.
func void release(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#delete","title":"delete
","text":"delete
Cleans the handle just like clear
, only the destructor is also called.
func void delete(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#free","title":"free
","text":"free
Similar to delete
, only here a pointer is destroyed and not a handle. Caution! Not managed by PermMem!
func void free(var int ptr, var int inst)\n
Parameters var int ptr
The pointer to be cleaned var int inst
Instance used in create
function. "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#get","title":"get
","text":"get
Returns the instance of the handle.
func instance get(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#getptr","title":"getPtr
","text":"getPtr
Returns a pointer to instance of handle.
func int getPtr(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#setptr","title":"setPtr
","text":"setPtr
Sets the pointer of a handle.
func void setPtr(var int hndl, var int ptr)\n
Parameters var int hndl
Valid PermMem handle var int ptr
New pointer for handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#getinst","title":"getInst
","text":"getInst
Returns the instance used to create the given handle in new
function.
func int getInst(var int hndl)\n
Parameters var int hndl
Valid PermMem handle "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#numhandles","title":"numHandles
","text":"numHandles
Returns the number of handles managed by PermMem.
func int numHandles()\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#sizeof","title":"sizeof
","text":"sizeof
Gets the size of the given instance's class.
func int sizeof(var int inst)\n
Parameters var int inst
Any instance Return value
The function returns the size of a given instance's class in bytes.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#hlp_isvalidhandle","title":"Hlp_IsValidHandle
","text":"Hlp_IsValidHandle
Indicates whether the handle exists and is managed by PermMem.
func int Hlp_IsValidHandle(var int hndl)\n
Parameters var int hndl
PermMem's handle Return value
The function returns TRUE
if the handle is valid (managed by PermMem), FALSE
is returned otherwise.
Example The example function that use Hlp_IsValidHandle
is Bar_SetMax
form LeGo Bars package. The function first checks if the handle is valid, then gets the instance and changes its parameters.
func void Bar_SetMax(var int bar, var int max) \n{\n if(!Hlp_IsValidHandle(bar)) { return; };\n var _bar b; b = get(bar);\n b.valMax = max;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#foreachhndl","title":"foreachHndl
","text":"foreachHndl
Executes a function for each handle of an instance.
func void foreachHndl(var int inst, var func fnc)\n
Parameters var int inst
The function is called for this instance var int inst
This function is called. The signature is function(int handle)
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#hashndl","title":"hasHndl
","text":"hasHndl
Checks if PermMem has a handle of this instance.
func int hasHndl(var int inst)\n
Parameters var int inst
Instance to be checked Return value
The function returns TRUE
if the PermMem has a handle of this instance, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#mem_readstringarray","title":"MEM_ReadStringArray
","text":"MEM_ReadStringArray
Function moved to PermMem form Ikarus. Reads string from the array at the arrayAddress
.
func string MEM_ReadStringArray(var int arrayAddress, var int index)\n
Parameters var int arrayAddress
Memory address of array var int offset
Array offset (array index) Return value
The function returns string from the array if the address is correct.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_exists","title":"PM_Exists
","text":"PM_Exists
Checks if the specified field already exists in the archive. (used with archiver/unarchiver)
func int PM_Exists(var string name)\n
Parameters var string name
Name of the field Return value
The function returns TRUE
if the field exists in the archive, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#archiver","title":"Archiver","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveint","title":"PM_SaveInt
","text":"PM_SaveInt
Saves an integer to the archive.
func void PM_SaveInt (var string name, var int val)\n
Parameters var string name
Name of the field in saved archive var int val
Value of the saved integer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefloat","title":"PM_SaveFloat
","text":"PM_SaveFloat
Saves a daedalus float to the archive.
func void PM_SaveFloat (var string name, var int flt)\n
Parameters var string name
Name of the field in saved archive var int flt
Value of the saved float "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savestring","title":"PM_SaveString
","text":"PM_SaveString
Saves a string to the archive.
func void PM_SaveString (var string name, var string val)\n
Parameters var string name
Name of the field in saved archive var string val
Saved string "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncid","title":"PM_SaveFuncID
","text":"PM_SaveFuncID
Saves a function ID to the archive.
func void PM_SaveFuncID(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function ID "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncoffset","title":"PM_SaveFuncOffset
","text":"PM_SaveFuncOffset
Saves a function offset to the archive.
func void PM_SaveFuncOffset(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function offset "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savefuncptr","title":"PM_SaveFuncPtr
","text":"PM_SaveFuncPtr
Saves a function pointer to the archive.
func void PM_SaveFuncPtr(var string name, var int fnc)\n
Parameters var string name
Name of the field in saved archive var int fnc
Saved function pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveclassptr","title":"PM_SaveClassPtr
","text":"PM_SaveClassPtr
Saves a pointer of a class to the archive.
func void PM_SaveClassPtr(var string name, var int ptr, var string className)\n
Parameters var string name
Name of the field in saved archive var int ptr
Saved pointer var string className
Name of the class of stored pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveclass","title":"PM_SaveClass
","text":"PM_SaveClass
Saves a class like PM_SaveClassPtr
.
func void PM_SaveClass(var string name, var int ptr, var string className)\n
Parameters var string name
Name of the field in saved archive var int ptr
Saved class pointer var string className
Name of the class of stored pointer "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_saveintarray","title":"PM_SaveIntArray
","text":"PM_SaveIntArray
Saves an array of integers.
func void PM_SaveIntArray(var string name, var int ptr, var int elements)\n
Parameters var string name
Name of the field in saved archive var int ptr
Pointer to the array var int elements
Number of elements in array "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_savestringarray","title":"PM_SaveStringArray
","text":"PM_SaveStringArray
Saves an array of integers.
func void PM_SaveStringArray(var string name, var int ptr, var int elements)\n
Parameters var string name
Name of the field in saved archive var int ptr
Pointer to the array var int elements
Number of elements in array "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#unarchiver","title":"Unarchiver","text":""},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_load","title":"PM_Load
","text":"PM_Load
Universal function to load integers, floats, class pointers and int arrays.
func int PM_Load(var string name)\n
Parameters var string name
Name of the loaded field Return value The function returns the data existing in the archive at the given field.
"},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadint","title":"PM_LoadInt
","text":"PM_LoadInt
Returns an integer stored in the archive.
func int PM_LoadInt(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfloat","title":"PM_LoadFloat
","text":"PM_LoadFloat
Returns a daedalus float stored in the archive.
func int PM_LoadFloat(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadstring","title":"PM_LoadString
","text":"PM_LoadString
Returns a string stored in the archive.
func string PM_LoadString(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncid","title":"PM_LoadFuncID
","text":"PM_LoadFuncID
Returns a function ID stored in the archive.
func int PM_LoadFuncID(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncoffset","title":"PM_LoadFuncOffset
","text":"PM_LoadFuncOffset
Returns a function offset stored in the archive.
func int PM_LoadFuncOffset(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadfuncptr","title":"PM_LoadFuncPtr
","text":"PM_LoadFuncPtr
Returns a function pointer stored in the archive.
func int PM_LoadFuncPtr(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadclassptr","title":"PM_LoadClassPtr
","text":"PM_LoadClassPtr
Returns a class pointer stored in the archive.
func int PM_LoadClassPtr(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadclass","title":"PM_LoadClass
","text":"PM_LoadClass
Loads a pointer to the class from the archive to destPtr
.
func void PM_LoadClass(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadarray","title":"PM_LoadArray
","text":"PM_LoadArray
Returns a pointer to array stored in the archive.
func int PM_LoadArray(var string name)\n
Parameters var string name
Name of the loaded field "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadarraytoptr","title":"PM_LoadArrayToPtr
","text":"PM_LoadArrayToPtr
Loads a pointer to array from the archive to destPtr
.
func void PM_LoadArrayToPtr(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/permmem/#pm_loadtoptr","title":"PM_LoadToPtr
","text":"PM_LoadToPtr
Universal function to load array or class pointer from the archive to destPtr
.
func void PM_LoadToPtr(var string name, var int destPtr)\n
Parameters var string name
Name of the loaded field var int destPtr
Destination pointer, the address to where it will deserialize the saved data "},{"location":"zengin/scripts/extenders/lego/tools/queue/","title":"Queue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#queue","title":"Queue","text":"Info
Dependencies: - PermMem Implementation: Queue.d on GitHub
This package is an implementation of the Queue data structure and a queue for function calls.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#queue_1","title":"Queue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_create","title":"Q_Create
","text":"Q_Create
Creates a new queue and returns a handle to it.
func int Q_Create()\n
Return value The function returns a handle to a queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_enqueue","title":"Q_Enqueue
","text":"Q_Enqueue
Appends an integer to the back of the queue
func void Q_Enqueue(var int queue, var int value)\n
Parameters var int queue
Handle of a queue var int value
The value to be appended to the queue "},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_isempty","title":"Q_IsEmpty
","text":"Q_IsEmpty
Checks if the queue is empty.
func int Q_IsEmpty(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns TRUE
if the queue is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_advance","title":"Q_Advance
","text":"Q_Advance
Removes the oldest value from the queue and returns it.
func int Q_Advance(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns the oldest value in the queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_peek","title":"Q_Peek
","text":"Q_Peek
Returns the oldest value in the queue without removing it.
func int Q_Peek(var int queue)\n
Parameters var int queue
Handle of a queue Return value
The function returns the oldest value in the queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_for","title":"Q_For
","text":"Q_For
Function with the funcID
is called with every element of the list as parameter. The list element is passed to the function as a zCList
pointer.
func void Q_For(var int queue, var int funcID)\n
Parameters var int queue
Handle of a queue var int funcID
ID of function that is executed for all values in the queue (signature: void (zCList*)
) "},{"location":"zengin/scripts/extenders/lego/tools/queue/#q_forf","title":"Q_ForF
","text":"Q_ForF
Like Q_For
, but with function as a parameter instead of a function ID.
func void Q_ForF(var int queue, var func f)\n
Parameters var int queue
Handle of a queue var func f
This function is executed for all values in the queue (signature: void (zCList*)
) "},{"location":"zengin/scripts/extenders/lego/tools/queue/#callbackqueue","title":"CallbackQueue","text":""},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_create","title":"CQ_Create
","text":"CQ_Create
Creates a new callback queue and returns a handle to it.
func int CQ_Create()\n
Return value The function returns a handle to a callback queue.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueuenodata","title":"CQ_EnqueueNoData
","text":"CQ_EnqueueNoData
Appends a function to the callback queue.
func void CQ_EnqueueNoData(var int queue, var func function)\n
Parameters var int queue
Handle of a callback queue var func function
A function with no return value, expecting no parameter "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueuedata","title":"CQ_EnqueueData
","text":"CQ_EnqueueData
Appends a function together with a value to the callback queue.
func void CQ_EnqueueData(var int queue, var func function, var int data)\n
Parameters var int queue
Handle of a callback queue var func function
A function with no return value, expecting an integer as a parameter. var int data
When calling function
, this value is passed as a parameter "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_enqueue","title":"CQ_Enqueue
","text":"CQ_Enqueue
Appends a function together with an optional value to the callback queue. This function should not usually be used. Use CQ_EnqueueData
and CQ_EnqueueNoData
instead.
func void CQ_Enqueue(var int queue, var int funcID, var int data, var int hasData)\n
Parameters var int queue
Handle of a callback queue var int funcID
The function ID of a function to be appended to the callback queue. var int data
If hasData is not 0, this value is passed to the associated function. var int hasData
Must be 0 if the function does not expect an integer as a parameter, otherwise not 0. "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_isempty","title":"CQ_IsEmpty
","text":"CQ_IsEmpty
Checks if no function is in the callback queue.
func int CQ_IsEmpty(var int queue)\n
Parameters var int queue
Handle of a callback queue Return value
The function returns TRUE
if the callback queue is empty, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_advance","title":"CQ_Advance
","text":"CQ_Advance
Executes the foremost function of the callback queue and removes it from the callback queue.
func void CQ_Advance(var int queue)\n
Parameters var int queue
Handle of a callback queue "},{"location":"zengin/scripts/extenders/lego/tools/queue/#cq_exhaust","title":"CQ_Exhaust
","text":"CQ_Exhaust
Executes all functions contained in the callback queue.
func void CQ_Exhaust(var int queue)\n
Parameters var int queue
Handle of a callback queue "},{"location":"zengin/scripts/extenders/lego/tools/random/","title":"Random","text":""},{"location":"zengin/scripts/extenders/lego/tools/random/#random","title":"Random","text":"Info
Dependencies: - None Implementation: Random.d on GitHub
Provides more random randomization than Hlp_Random()
function.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#initialization","title":"Initialization","text":"Initialize with LeGo_Random
flag.
LeGo_Init(LeGo_Random);\n
"},{"location":"zengin/scripts/extenders/lego/tools/random/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/random/#r_next","title":"r_Next
","text":"r_Next
Returns a random number.
func int r_Next()\n
Return value The function returns a random number.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_max","title":"r_Max
","text":"r_Max
Returns a random number from 0 to max
.
func int r_Max(var int max)\n
Parameters var int max
Maximum value of number Return value
The function returns a random number from 0 to 'max'.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_minmax","title":"r_MinMax
","text":"r_MinMax
Returns a random number from 'min' to 'max'.
func int r_MinMax(var int min, var int max)\n
Parameters var int max
Maximum value of number var int min
Minimum value of number Return value
The function returns a random number from min
to max
.
"},{"location":"zengin/scripts/extenders/lego/tools/random/#r_init","title":"r_Init
","text":"r_Init
Initializes the random number generator. Happens optionally in LeGo_Init
.
func void r_Init(var int seed)\n
Parameters var int seed
The initializing value "},{"location":"zengin/scripts/extenders/lego/tools/random/#r_defaultinit","title":"r_DefaultInit
","text":"r_DefaultInit
Initializes the random number generator based on the current time.
func void r_DefaultInit()\n
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/","title":"Sprite","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite","title":"Sprite","text":"Info
Dependencies: - PermMem Implementation: Sprite.d on GitHub
Sprite package implements functions for working with 2D sprites.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#initialization","title":"Initialization","text":"Initialize with LeGo_Sprite
flag.
LeGo_Init(LeGo_Sprite);\n
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_create","title":"Sprite_Create
","text":"Sprite_Create
Creates a sprite. The dimensions are in virtual coordinates.
func int Sprite_Create(var int x, var int y, var int width, var int height, var int color, var string tex)\n
Parameters var int x
X position of sprite (virtual) var int y
Y position of sprite (virtual) var int width
Width of sprite (virtual) var int height
Height of sprite (virtual) var int color
Color of sprite (in RGBA format) var string tex
Name of the sprite texture Return value
The function returns the handle of the created sprite.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_createpxl","title":"Sprite_CreatePxl
","text":"Sprite_CreatePxl
Creates a sprite. The dimensions are in pixels.
func int Sprite_CreatePxl(var int x, var int y, var int width, var int height, var int color, var string tex)\n
Parameters var int x
X position of sprite (pixels) var int y
Y position of sprite (pixels) var int width
Width of sprite (pixels) var int height
Height of sprite (pixels) var int color
Color of sprite (in RGBA format) var string tex
Name of the sprite texture Return value
The function returns the handle of the created sprite.
"},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_render","title":"Sprite_Render
","text":"Sprite_Render
Renders a sprite on a screen (must be visible first).
func void Sprite_Render(var int h)\n
Parameters var int h
Handle of the sprite "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvisible","title":"Sprite_SetVisible
","text":"Sprite_SetVisible
Sets the visibility of a sprite.
func void Sprite_SetVisible(var int h, var int visible)\n
Parameters var int h
Handle of the sprite var int visible
Visibility flag (0 for invisible, 1 for visible) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setprio","title":"Sprite_SetPrio
","text":"Sprite_SetPrio
Sets the priority of a sprite. The higher the priority, the closer the sprite is to the camera.
func void Sprite_SetPrio(var int h, var int prio)\n
Parameters var int h
Handle of the sprite var int prio
Priority of the sprite "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_scale","title":"Sprite_Scale
","text":"Sprite_Scale
Scales a sprite.
func void Sprite_Scale(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X scale factor (as ikarus float) var int y
Y scale factor (as ikarus float) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setwidth","title":"Sprite_SetWidth
","text":"Sprite_SetWidth
Sets the width of a sprite in virtual coordinates.
func void Sprite_SetWidth(var int h, var int w)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setwidthpxl","title":"Sprite_SetWidthPxl
","text":"Sprite_SetWidthPxl
Sets the width of a sprite in pixels.
func void Sprite_SetWidthPxl(var int h, var int w)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setheight","title":"Sprite_SetHeight
","text":"Sprite_SetHeight
Sets the height of a sprite in virtual coordinates.
func void Sprite_SetHeight(var int h, var int hg)\n
Parameters var int h
Handle of the sprite var int hg
Height of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setheightpxl","title":"Sprite_SetHeightPxl
","text":"Sprite_SetHeightPxl
Sets the height of a sprite in pixels.
func void Sprite_SetHeightPxl(var int h, var int hg)\n
Parameters var int h
Handle of the sprite var int hg
Height of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setdim","title":"Sprite_SetDim
","text":"Sprite_SetDim
Sets the dimensions of a sprite in virtual coordinates.
func void Sprite_SetDim(var int h, var int w, var int hg)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in virtual coordinates var int hg
Height of the sprite in virtual coordinates "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setdimpxl","title":"Sprite_SetDimPxl
","text":"Sprite_SetDimPxl
Sets the dimensions of a sprite in pixels.
func void Sprite_SetDimPxl(var int h, var int w, var int hg)\n
Parameters var int h
Handle of the sprite var int w
Width of the sprite in pixels var int hg
Height of the sprite in pixels "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpos","title":"Sprite_SetPos
","text":"Sprite_SetPos
Sets the position of a sprite in virtual coordinates.
func void Sprite_SetPos(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X position of the sprite (virtual) var int y
Y position of the sprite (virtual) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpospxl","title":"Sprite_SetPosPxl
","text":"Sprite_SetPosPxl
Sets the position of a sprite in pixels.
func void Sprite_SetPosPxl(var int h, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int x
X position of the sprite (pixels) var int y
Y position of the sprite (pixels) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setpospxlf","title":"Sprite_SetPosPxlF
","text":"Sprite_SetPosPxlF
Sets the position of a sprite in pixels (floating point).
func void Sprite_SetPosPxlF(var int h, var int xf, var int yf)\n
Parameters var int h
Handle of the sprite var int xf
X position of the sprite (pixels but as a float) var int yf
Y position of the sprite (pixels but as a float) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setcolor","title":"Sprite_SetColor
","text":"Sprite_SetColor
Sets the color of a sprite.
func void Sprite_SetColor(var int h, var int col)\n
Parameters var int h
Handle of the sprite var int col
Color of the sprite (in RGBA format) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvertcolor","title":"Sprite_SetVertColor
","text":"Sprite_SetVertColor
Sets the color of a vertex in a sprite.
func void Sprite_SetVertColor(var int h, var int vert, var int col)\n
Parameters var int h
Handle of the sprite var int vert
Index of the vertex (0-3) var int col
Color of the vertex (in RGBA format) "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setuv","title":"Sprite_SetUV
","text":"Sprite_SetUV
Sets the UV coordinates of a sprite.
func void Sprite_SetUV(var int h, var int x0, var int y0, var int x1, var int y1)\n
Parameters var int h
Handle of the sprite var int x0
X coordinate of the top-left UV var int y0
Y coordinate of the top-left UV var int x1
X coordinate of the bottom-right UV var int y1
Y coordinate of the bottom-right UV "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setvertuv","title":"Sprite_SetVertUV
","text":"Sprite_SetVertUV
Sets the UV coordinates of a vertex in a sprite.
func void Sprite_SetVertUV(var int h, var int vert, var int x, var int y)\n
Parameters var int h
Handle of the sprite var int vert
Index of the vertex (0-3) var int x
X coordinate of the UV var int y
Y coordinate of the UV "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_rotate","title":"Sprite_Rotate
","text":"Sprite_Rotate
Rotates a sprite by a given angle in degrees.
func void Sprite_Rotate(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_rotater","title":"Sprite_RotateR
","text":"Sprite_RotateR
Rotates a sprite by a given angle in radians.
func void Sprite_RotateR(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in radians "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotation","title":"Sprite_SetRotation
","text":"Sprite_SetRotation
Sets the rotation of a sprite in degrees.
func void Sprite_SetRotation(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotationr","title":"Sprite_SetRotationR
","text":"Sprite_SetRotationR
Sets the rotation of a sprite in radians.
func void Sprite_SetRotationR(var int h, var int r)\n
Parameters var int h
Handle of the sprite var int r
Rotation angle in radians "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sprite_setrotationsc","title":"Sprite_SetRotationSC
","text":"Sprite_SetRotationSC
Sets the rotation of a sprite using sine and cosine values.
func void Sprite_SetRotationSC(var int h, var int sin, var int cos)\n
Parameters var int h
Handle of the sprite var int sin
Sine value of the rotation var int cos
Cosine value of the rotation "},{"location":"zengin/scripts/extenders/lego/tools/sprite/#helper-functions","title":"Helper functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/sprite/#sincosapprox","title":"SinCosApprox
","text":"SinCosApprox
Approximates sine and cosine values for a given angle. Keeps them in var int sinApprox
var int cosApprox;
variables.
func void SinCosApprox(var int angle)\n
Parameters var int angle
Angle in degrees "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/","title":"StringBuilder","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#stringbuilder","title":"StringBuilder","text":"Info
Dependencies: - None Implementation: StringBuilder.d on GitHub
The StringBuilder is a package, designed to easily concatenate multiple elements into a string (without ConcatStrings
and IntToString
).
All created StringBuilders are transient. All functions starting from SB_InitBuffer
, including it, use the active StringBuilder set with SB_New
or SB_Use
, so there is no var int stringBuilder
parameter in functions. A look at the example explains what I mean.
Warning
The StringBuilder works with pointers, not handles like many other LeGo packages.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#initialization","title":"Initialization","text":"N/A
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_new","title":"SB_New
","text":"SB_New
Creates and returns a new StringBuilder
. At the same time, this new StringBuilder
is set as active. (See SB_Use
.)
func int SB_New()\n
Return value The function returns a pointer to a new StringBuilder
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_use","title":"SB_Use
","text":"SB_Use
Marks this StringBuilder
as active. It can now be used with the functions.
func void SB_Use(var int sb)\n
Parameters var int sb
Pointer to a StringBuilder
, returned from SB_New
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_get","title":"SB_Get
","text":"SB_Get
Returns the active StringBuilder
.
func int SB_Get()\n
Return value The function returns the active StringBuilder
object - last set with SB_Use
or just created with SB_New
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_initbuffer","title":"SB_InitBuffer
","text":"SB_InitBuffer
If the size of the resulting string is already known, the buffer can be set manually. This is usually not necessary.
func void SB_InitBuffer(var int size)\n
Parameters var int size
Size in bytes. Warning! Only works if the StringBuilder
has been newly created! "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_clear","title":"SB_Clear
","text":"SB_Clear
Empties the current StringBuilder
. It is not destroyed in the process, so it can be used again. If the object has a buffer allocated, the buffer is freed.
func void SB_Clear()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_release","title":"SB_Release
","text":"SB_Release
Releases the current stream of the StringBuilder
. The StringBuilder
is destroyed, and the stream can be obtained via SB_GetStream
.
func void SB_Release()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_destroy","title":"SB_Destroy
","text":"SB_Destroy
Completely destroys the StringBuilder
.
func void SB_Destroy()\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_tostring","title":"SB_ToString
","text":"SB_ToString
Returns a copy of the stream as a string.
func string SB_ToString()\n
Return value The function returns the copy of the active StringBuilder
as a string. If the StringBuilder
object doesn't have a buffer allocated, an empty string is returned.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_tostream","title":"SB_ToStream
","text":"SB_ToStream
Returns a copy of the stream in raw format.
func int SB_ToStream()\n
Return value The function returns a copy of the stream in raw format (char[]
)
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_getstream","title":"SB_GetStream
","text":"SB_GetStream
Doesn't copy the stream, but returns it as it is.
func int SB_GetStream()\n
Return value The function returns the stream as it is. SB_Destroy
or SB_Clear
destroy the returned pointer.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_length","title":"SB_Length
","text":"SB_Length
Returns the current length of the stream. Similar to STR_Len
from Ikarus .
func int SB_Length()\n
Return value The function returns the current length of the active StringBuilder
.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb_setlength","title":"SB_SetLength
","text":"SB_SetLength
Sets the length of the stream. When increasing, zero bytes are appended.
func void SB_SetLength(var int length)\n
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#stream-operations","title":"Stream operations","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sb","title":"SB
","text":"SB
Appends a string, to the active StringBuilder
.
func void SB(var string s)\n
Parameters var string s
The appended string "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbi","title":"SBi
","text":"SBi
Appends an integer in text form, to the active StringBuilder
.
func void SBi(var int i)\n
Parameters var int i
The appended integer "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbc","title":"SBc
","text":"SBc
Appends a byte, to the active StringBuilder
. (e.g. 82 for 'R' - An ASCII table can be quickly found)
func void SBc(var int c)\n
Parameters var int c
The appended byte (ASCII table character) "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbraw","title":"SBraw
","text":"SBraw
Appends a raw bytes array, to the active StringBuilder
.
func void SBraw(var int ptr, var int len)\n
Parameters var int ptr
Pointer to the appended array var int len
Length of an array "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbflt","title":"SBflt
","text":"SBflt
Appends a Daedalus float in text form, to the active StringBuilder
.
func void SBflt(var float x)\n
Parameters var float x
The appended Daedalus float value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbf","title":"SBf
","text":"SBf
Appends an Ikarus float in text form, to the active StringBuilder
.
func void SBf(var int x)\n
Parameters var float x
The appended Ikarus float value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#sbw","title":"SBw
","text":"SBw
Appends a 4-byte raw data (interpreted as an integer x
), to the active StringBuilder
.
func void SBw(var int x)\n
Parameters var int i
The appended value "},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#independent-functions","title":"Independent Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_escape","title":"STR_Escape
","text":"STR_Escape
Makes escape sequences out of non-writable characters. For example, newline character \\n
becomes \\\\n
, tab character \\t
becomes \\\\t
, etc.
func string STR_Escape(var string s0)\n
Parameters var string s0
The string to be added escape sequences Return value
The function returns a new string with escape sequences added for special characters.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_unescape","title":"STR_Unescape
","text":"STR_Unescape
Counterpart to STR_Escape
. Escape sequences like \\n
, \\r
or \\t
are converted back.
func string STR_Unescape(var string s0)\n
Parameters var string s0
The string to be removed escape sequences Return value
The function returns a new string with escape sequences replaced by their corresponding characters.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#str_startswith","title":"STR_StartsWith
","text":"STR_StartsWith
Checks if the input string s
starts with the specified prefix string.
func int STR_StartsWith(var string str, var string start) \n
Parameters var string str
The string to be checked var string start
The searched prefix Return value
The function returns TRUE
if the string starts with the prefix, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#additional-functions","title":"Additional Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#buildstringsymbolsarray","title":"BuildStringSymbolsArray
","text":"BuildStringSymbolsArray
Creates an array of all string symbols found in the parser's string table.
func int BuildStringSymbolsArray()\n
Return value The function returns created array.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#getstringsymbolbyaddr","title":"GetStringSymbolByAddr
","text":"GetStringSymbolByAddr
Retrieves the symbol at the specified address from the string table.
func int BuildStringSymbolsArray()\n
Return value The function returns a parser symbol at the given address.
"},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#basic-functionality","title":"Basic functionality","text":"This is how function that builds a string looks without StringBuilder
:
func void PrintMyNumbers(var int x0, var int x1, var int x2) {\n var string res;\n res = ConcatStrings(IntToString(x0), \", \");\n res = ConcatStrings(res, IntToString(x1));\n res = ConcatStrings(res, \", \");\n res = ConcatStrings(res, IntToString(x2));\n PrintS(res);\n};\n
And now the function that uses StringBulider
: func void PrintMyNumbers(var int x0, var int x1, var int x2) {\n var int s; s = SB_New(); // Create StringBuilder\n SBi(x0); // Append Int\n SB (\", \"); // Append string\n SBi(x1); // Append Int\n SB (\", \"); // Append string\n SBi(x2); // Append Int\n PrintS(SB_ToString()); // Get output as a string\n SB_Destroy(); // Destroy StringBuilder\n};\n
Looks much more pleasant, right? But why do we create a StringBuilder and then not use it? The idea is the following: A StringBuilder is created with SB_New()
and set as the active StringBuilder in the background. The package only supports one StringBuilder at a time, which will keep the pointer in case we want to use another StringBuilder in between."},{"location":"zengin/scripts/extenders/lego/tools/string_builder/#multiple-stringbuilders","title":"Multiple StringBuilders","text":"Simple example. We want to fill two StringBuilders at the same time and then return them combined:
func string Example2() {\n // Create two StringBuilders:\n var int s0; s0 = SB_New();\n var int s1; s1 = SB_New();\n\n // Set the first StringBuilder as active and fill it.\n SB_Use(s0);\n SB(\"Hello \");\n SB(\"World!\");\n\n // Set the second StringBuilder as active and fill it.\n SB_Use(s1);\n SB(\"This is \");\n SB(\"the hero speaking!\");\n\n // Now we want to combine the two StringBuilders.\n // The system doesn't actually provide for such an operation, but it can still be done using a helper string\n var string str; str = SB_ToString(); // This string now says \u201cThis is the hero speaking!\u201d\n\n SB_Use(s0);\n SB(\" \");\n SB(str);\n\n str = SB_ToString(); // Now \"Hello world! This is the hero speaking!\" are in the string.\n\n // The rest is already known, we destroy StringBuilders\n SB_Destroy();\n SB_Use(s1);\n SB_Destroy();\n\n return str;\n};\n
"},{"location":"zengin/scripts/extenders/lego/tools/talents/","title":"Talents","text":""},{"location":"zengin/scripts/extenders/lego/tools/talents/#talents","title":"Talents","text":"Info
Dependencies: - PermMem Implementation: Talents.d on GitHub
The Talents package does two things:
save any number of values for a specific NPC (effectively AIVar array extension). identify NPC by unique ID. Talents package uses one free AIVar variables, the default is AIVar with the index 89 that can be customized in Userconst.d
the AIV_TALENT
constant.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#initialization","title":"Initialization","text":"Initialize with LeGo_PermMem
flag.
LeGo_Init(LeGo_PermMem);\n
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/talents/#npc_getid","title":"Npc_GetID
","text":"Npc_GetID
Returns unique ID specific for provided NPC.
func int Npc_GetID(var C_NPC slf)\n
Parameters var C_NPC slf
NPC to get ID Return value
The function returns NPCs unique ID.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#npc_findbyid","title":"Npc_FindByID
","text":"Npc_FindByID
Finds the NPC pointer of an NPC with the given ID.
func int Npc_FindByID(var int ID)\n
Parameters Return value
The function returns NPC pointer.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_createtalent","title":"TAL_CreateTalent
","text":"TAL_CreateTalent
Creates a talent into which you can later save a value for every NPC (just like AI_Var
).
func int TAL_CreateTalent()\n
Return value The function returns value that can be later used as a talent ID.
"},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_setvalue","title":"TAL_SetValue
","text":"TAL_SetValue
Sets a new value to the specified talent.
func void TAL_SetValue(var C_NPC npc, var int talent, var int value)\n
Parameters var C_NPC npc
Set the talent value for this NPC var int talent
Talent ID var int value
Value to be set "},{"location":"zengin/scripts/extenders/lego/tools/talents/#tal_getvalue","title":"TAL_GetValue
","text":"TAL_GetValue
Returns the value of a saved talent for specified NPC.
func int TAL_GetValue(var C_NPC npc, var int talent)\n
Parameters var C_NPC npc
Get the talent value from this NPC var int talent
Talent ID "},{"location":"zengin/scripts/extenders/lego/tools/timer/","title":"Timer","text":""},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer","title":"Timer","text":"Info
Dependencies: - None Implementation: Timer.d on GitHub
Timer is a better alternative to the timers that Gothic offers. The FrameFunctions and Anim8 packages are already based on it. It isn't possible to modify the current time, as this would only cause difficulties.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#initialization","title":"Initialization","text":"Initialize with LeGo_Timer
flag.
LeGo_Init(LeGo_Timer);\n
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_1","title":"Timer
","text":"Timer
Returns the current playing time. If a new game is started, the time is 0. It is measured in milliseconds.
func int Timer()\n
Return value The function returns current playing time in milliseconds.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timergt","title":"TimerGT
","text":"TimerGT
Returns the current game time, but the timer is paused when the game is paused (in the menu or status screen).
func int TimerGT()\n
Return value The function returns current playing time in milliseconds, but without measuring time when game is paused.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timerf","title":"TimerF
","text":"TimerF
Alias to Timer
function that returns the time as an Ikarus float value.
func int TimerF()\n
Return value The function returns current playing time as an Ikarus float value.
"},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_setpause","title":"Timer_SetPause
","text":"Timer_SetPause
Pauses the timer (and thus all FrameFunctions and running animations).
func void Timer_SetPause(var int on)\n
Parameters "},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_setpauseinmenu","title":"Timer_SetPauseInMenu
","text":"Timer_SetPauseInMenu
The timer can automatically pause when the game is paused. (status screen, main menu...)
func void Timer_SetPauseInMenu(var int on)\n
Parameters var int on
Automatic pause on/off "},{"location":"zengin/scripts/extenders/lego/tools/timer/#timer_ispaused","title":"Timer_IsPaused
","text":"Timer_IsPaused
This can be used to query whether the timer is paused.
func int Timer_IsPaused()\n
Return value The function returns TRUE
if the timer is paused, FALSE
is returned otherwise.
"},{"location":"zengin/scripts/extenders/lego/tools/view/","title":"View","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#view","title":"View","text":"Info
Dependencies: - PermMem - Interface Implementation: View.d on GitHub
This package can create textures on the screen and work with them in an extended manner.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#initialization","title":"Initialization","text":"Initialize with LeGo_View
flag.
LeGo_Init(LeGo_View);\n
"},{"location":"zengin/scripts/extenders/lego/tools/view/#functions","title":"Functions","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#view_create","title":"View_Create
","text":"View_Create
Creates a zCView
with virtual coordinates.
func int View_Create(var int x1, var int y1, var int x2, var int y2) \n
Parameters var int x1
/var int y1
Top-left corner coordinates (virtual) var int x2
/var int y2
Bottom-right corner coordinates (virtual) Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createpxl","title":"View_CreatePxl
","text":"View_CreatePxl
Alias for View_Create
using pixel coordinates.
func int View_CreatePxl(var int x1, var int y1, var int x2, var int y2) \n
Parameters var int x1
/var int y1
Top-left corner coordinates (pixel) var int x2
/var int y2
Bottom-right corner coordinates (pixel) Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createcenter","title":"View_CreateCenter
","text":"View_CreateCenter
Creates a zCView
with virtual coordinates centered.
func int View_CreateCenter(var int x, var int y, var int width, var int height)\n
Parameters var int x
Horizontal position var int y
Vertical position var int width
Width of the view var int height
Height of the view Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_createcenterpxl","title":"View_CreateCenterPxl
","text":"View_CreateCenterPxl
Alias for View_CreateCenter
using pixel coordinates.
func int View_CreateCenterPxl(var int x, var int y, var int width, var int height)\n
Parameters var int x
Horizontal position var int y
Vertical position var int width
Width of the view var int height
Height of the view Return value
The function returns a PermMem handle to a zCView
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_get","title":"View_Get
","text":"View_Get
Alias for get
form PermMem.
zCView View_Get(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_getptr","title":"View_GetPtr
","text":"View_GetPtr
Alias for getPtr
form PermMem.
func int View_GetPtr(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_render","title":"View_Render
","text":"View_Render
Renders a zCView
. Should be used sparingly, as it works only in specific cases.
func void View_Render(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_settexture","title":"View_SetTexture
","text":"View_SetTexture
Assigns a texture to a view. The key function of this package.
func void View_SetTexture(var int hndl, var string texture)\n
Parameters var int hndl
Handle created with View_Create
var string texture
Filename of a texture "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_gettexture","title":"View_GetTexture
","text":"View_GetTexture
Gets the name of a previously assigned texture.
func string View_GetTexture(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
Return value
The function returns the previously assigned texture.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_setcolor","title":"View_SetColor
","text":"View_SetColor
Sets the color of a view.
func void View_SetColor(var int hndl, var int color)\n
Parameters var int hndl
Handle created with View_Create
var int color
zColor, can be created with RGBA "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_getcolor","title":"View_GetColor
","text":"View_GetColor
Gets the color of a view.
func int View_GetColor(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
Return value
The function returns the full zColor.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_open","title":"View_Open
","text":"View_Open
Opens a view. It will be displayed on the screen.
func void View_Open(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_close","title":"View_Close
","text":"View_Close
Closes a view. It disappears from the screen but can still be used.
func void View_Close(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_delete","title":"View_Delete
","text":"View_Delete
Alias for delete
.
`zCView` View_Delete(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_resize","title":"View_Resize
","text":"View_Resize
Scales a view to a virtual size. The top-left position of the view remains fixed.
func void View_Resize(var int hndl, var int width, var int height)\n
Parameters var int hndl
Handle created with View_Create
var int width
New width of the view var int height
New height of the view "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_resizepxl","title":"View_ResizePxl
","text":"View_ResizePxl
Alias for View_Resize
using pixel coordinates.
func void View_ResizePxl(var int hndl, var int width, var int height)\n
Parameters var int hndl
Handle created with View_Create
var int width
New width of the view var int height
New height of the view "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_move","title":"View_Move
","text":"View_Move
Moves the view by virtual units.
func void View_Move(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
Shift left/right var int y
Shift up/down "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_movepxl","title":"View_MovePxl
","text":"View_MovePxl
Alias for View_Move
using pixel coordinates.
func void View_MovePxl(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
Shift left/right var int y
Shift up/down "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_moveto","title":"View_MoveTo
","text":"View_MoveTo
Moves the top-left corner of the view to a virtual position.
func void View_MoveTo(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
New horizontal position (-1 for no change) var int y
New vertical position (-1 for no change) "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_movetopxl","title":"View_MoveToPxl
","text":"View_MoveToPxl
Alias for View_MoveTo
using pixel coordinates.
func void View_MoveToPxl(var int hndl, var int x, var int y)\n
Parameters var int hndl
Handle created with View_Create
var int x
New horizontal position (-1 for no change) var int y
New vertical position (-1 for no change) "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_addtext","title":"View_AddText
","text":"View_AddText
Adds a text line to the view. The position is virtual and relative to the view's position. If the view is moved, the text moves as well.
func void View_AddText(var int hndl, var int x, var int y, var string text, var string font)\n
Parameters var int hndl
Handle created with View_Create
var int x
Horizontal position var int y
Vertical position var string text
Added text var string font
Used Font "},{"location":"zengin/scripts/extenders/lego/tools/view/#view_deletetext","title":"View_DeleteText
","text":"View_DeleteText
Removes all text added with View_AddText
.
func void View_DeleteText(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#view_top","title":"View_Top
","text":"View_Top
Places the view above all others.
func void View_Top(var int hndl)\n
Parameters var int hndl
Handle created with View_Create
"},{"location":"zengin/scripts/extenders/lego/tools/view/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/lego/tools/view/#display-a-texture-on-the-screen","title":"Display a texture on the screen","text":"Here a texture should be displayed over the entire screen:
func void Example1() {\n var int View; \n View = View_Create(0, 0, PS_VMax, PS_VMax); // Virtual coordinates\n View_SetTexture(View, \"MyTexture.tga\"); // Assign a texture to the view\n // display the view on the screen:\n View_Open(View);\n};\n
This would mean that the texture would be permanently visible on the screen (even after loading/saving/restarting). If we want it to disappear we have to use either View_Delete
or View_Close
.
"},{"location":"zengin/scripts/extenders/lego/tools/view/#display-a-texture-with-pixel-coordinates","title":"Display a texture with pixel coordinates","text":"Now a texture should be displayed at the top right and be 256 x 256 pixels in size:
func void Example2() {\n Print_GetScreenSize();\n var int View;\n View = View_CreatePxl(Print_Screen[PS_X] - 256, 0, Print_Screen[PS_X], 256); // Pixel coordinates\n View_SetTexture(View, \"MYTEXTURE.TGA\");\n View_Open(View);\n};\n
To get the size of the screen we use the interface package.
"},{"location":"zengin/scripts/extenders/standalone/","title":"Standalone Scripts","text":""},{"location":"zengin/scripts/extenders/standalone/#standalone-scripts","title":"Standalone Scripts","text":"Over the years Gothic modders have created many useful features to use with Zengin scripts. This section contains documentation for some scripts that are \"standalone\", meaning they are not part of larger packages, but are often small features to make modders lives easier.
"},{"location":"zengin/scripts/extenders/standalone/#script-bins","title":"Script Bins","text":"A few people came up with the idea of collecting scripts scattered on the forums, which resulted in the so-called Script Bins.
Warning
Script bins aren't updated frequently, so for the latest updates and new scripts also check the ScriptBin WoG thread.
"},{"location":"zengin/scripts/extenders/standalone/#wog-script-bin","title":"WoG Script Bin","text":"Script bin made by Kirides containing scripts from German WoG forum.
https://apps.kirides.de/wog-script-bin/
"},{"location":"zengin/scripts/extenders/standalone/#scriptbin-github-repository","title":"ScriptBin GitHub repository","text":"Lehona has created a GitHub repository that contains scripts from some of the modders.
https://github.com/Lehona/ScriptBin
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/","title":"gameKeyEvents","text":""},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#gamekeyevents","title":"gameKeyEvents","text":"Quick overview
Author: mud-freak Platform: G1, G2NotR Category: Engine, Keys
gameKeyEvents.d is a script, which handles key events with the oCGame::HandleEvent
hook. Better alternative for FrameFunction
with MEM_KeyState
with which you don't have to check whether any menu is opened or player is in dialogue or can move etc.
Author's description I looked up the address within oCGame::HandleEvent
. I made it into a universally usable script for Gothic 1 and Gothic 2.
One could argue now that this is not much different from a FrameFunction
with MEM_KeyState
. The difference is that this approach saves the extra work of checking if any menu is open, whether the player is in a dialog, whether the player may move, etc. Also this function is \"event driven\", meaning it is really only called when a key is pressed/held instead of every frame in vain. So it's arguably more performant.
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#dependencies","title":"Dependencies","text":""},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#initialization","title":"Initialization","text":"Call Game_KeyEventInit()
in the Init_Global()
or other initialization function.
Game_KeyEventInit();\n
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#implementation","title":"Implementation","text":" gameKeyEvents.d on WoG forum
"},{"location":"zengin/scripts/extenders/standalone/gameKeyEvents/#usage","title":"Usage","text":"To add a key pressing detection edit the main function Game_KeyEvent
.
func int Game_KeyEvent(var int key, var int pressed) {\n if (key == KEY_LBRACKET) && (pressed) {\n // Here enter your code.\n return TRUE;\n };\n return FALSE;\n};\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/","title":"setBarPositions","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#setbarpositions","title":"setBarPositions","text":"Quick overview
Author: mud-freak Platform: G1, G2NotR Category: Engine, Interface
setBarPositions.d is a script that allows changing position of original gothic bars (HP, Mana, Swim, focus). Changes are directly in the engine, so bars are normally scaled.
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#dependencies","title":"Dependencies","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#initialization","title":"Initialization","text":"Call it in the Init_Global()
or other initialization function. Set the manaAlwaysOn
and swimAlwaysOn
to TRUE/FALSE.
SetBarPositions_Init(manaAlwaysOn, swimAlwaysOn);\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#implementation","title":"Implementation","text":" setBarPositions.d on WoG forum
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#usage","title":"Usage","text":"To change positions of bars edit the main function SetBarPosition
. Look at the examples to see how you can adjust it to your preferences.
func int SetBarPosition(var int barPtr) {\n var oCViewStatusBar bar; bar = _^(barPtr);\n var int x; var int y;\n\n if (barPtr == MEM_Game.hpBar) {\n // Original\n x = Print_ToVirtual(10, PS_X); // 10 px from the left\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.manaBar) {\n // Original\n x = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizex, PS_X); // 10 px from the right\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.swimBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom\n\n } else if (barPtr == MEM_Game.focusBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = Print_ToVirtual(10, PS_Y); // 10 px from the top\n };\n\n return x | (y << 14);\n};\n
"},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#examples","title":"Examples","text":""},{"location":"zengin/scripts/extenders/standalone/setBarPositions/#all-bars-on-the-left-side","title":"All bars on the left side","text":"/*\n * EXAMPLE: Stacked on the left\n */\nfunc int SetBarPosition(var int barPtr) {\n var oCViewStatusBar bar; bar = _^(barPtr);\n var int x; var int y;\n\n if (barPtr == MEM_Game.hpBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 3 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.manaBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 2 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.swimBar) {\n x = Print_ToVirtual(10, PS_X);\n y = PS_VMax - Print_ToVirtual(6 + 1 * (4 + bar.zCView_psizey), PS_Y);\n\n } else if (barPtr == MEM_Game.focusBar) {\n // Original\n x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered\n y = Print_ToVirtual(10, PS_Y); // 10 px from the top\n };\n\n return x | (y << 14);\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/","title":"zParserExtender","text":""},{"location":"zengin/scripts/extenders/zparserextender/#zparserextender","title":"zParserExtender","text":"zParserExtender extends ZenGin's parser and adds many useful features. It significantly extends the functionality of scripts with added functionality and new external functions. It also enhances script compilation, allowing to compile OU files directly with the game and allowing for runtime script injection. Since the Union version 1.0m
zParserExtender is fully integrated in Union itself.
Note
This is mostly a translation of the original release post
Contacts Author Gratt GitHub zParserExtender Forum zParserExtender"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/","title":"Trigger functions and the `C_Trigger` class","text":""},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#trigger-functions-and-the-c_trigger-class","title":"Trigger functions and the C_Trigger
class","text":"zParserExtender also implements cyclical functions called triggers - not to be confused with triggers in ZEN files, similar to a part of the functionality implemented in LeGo AI_Functions. These functions are called independently after a specified period of time. These triggers can also store user information. Up to 16 int variables can be stored in each trigger as well as self
, other
and victim
instances.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#class-definition","title":"Class definition","text":"To define a trigger, the C_Trigger
class is used:
/// Union zParserExtender Trigger class\nclass C_Trigger\n{\n var int Delay; // defines the frequency (in milliseconds) at which the function will be called.\n var int Enabled; // determines if the trigger is active. If the value is equal to zero, the trigger is destroyed.\n var int AIVariables[16]; // user data, which can be set independently when creating trigger (yes, you can write there absolutely everything you want).\n\n // Hidden variable members\n /*\n - Func - The function that the trigger will call.\n - Self - The NPC that will be placed in `self` when the function is called.\n - Other - An NPC that will be placed in `other` when the function is called.\n - Victim - The NPC that will be placed in `victim` when the function is called.\n */\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#creating-instances","title":"Creating instances","text":"There are two external functions that are used to create C_Trigger
instance.
// function returns a trigger with no NPC (self, other or victim) bound to it\nfunc C_Trigger AI_StartTriggerScript( var string funcName,\n var int delay) {};\n\n// function is extended, if certain participants need to be assigned to it\nfunc C_Trigger AI_StartTriggerScriptEx( var string funcName,\n var int delay,\n var C_Npc slf,\n var C_Npc oth,\n var C_Npc vct) {};\n
Both of these functions return an instance of C_Trigger
instance. You can of course configure the instance after its creation. You can, for example, fill in the AIVariables
with relevant data. The trigger function has the required signature if 'func int f()'. It must return a value indicating the state of the loop. If the function returns LOOP_END
the trigger will be stopped and the instance deleted. If LOOP_CONTINUE
is returned, the function will be called again after Delay
ms have passed.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#poison-example","title":"Poison example","text":"// Implement a trigger to simulate the effect of poison debuff:\n// Let's create a trigger on function `c_loop` with a call interval of 1 second.\n// When the function is called, the instance hero will be placed in self (although it can be any other NPC if desired).\n// The rest of the instances are left null (not used).\n\nvar C_Trigger trigger;\ntrigger = AI_StartTriggerScriptEx(\"c_loop\", 1000, hero, null, null);\ntrigger.AIVariables[0] = 15; // how many times the function should be called\ntrigger.AIVariables[1] = 5; // how much damage to deal each iteration\n
The trigger function
func int c_loop()\n{\n // Create a loop end check, if the number of\n // available iterations has reached 0. If it did\n // we stop the trigger by returning the LOOP_END value.\n if (SelfTrigger.AIVariables[0] <= 0)\n {\n return Loop_end;\n };\n\n SelfTrigger.Delay -= 20; // Accelerate loop each call by 20 ms\n SelfTrigger.AIVariables[0] -= 1; // Reduce number of remaining repeats\n self.Attribute[ATR_HITPOINTS] -= SelfTrigger.AIVariables[1]; // Take health from self\n return LOOP_CONTINUE;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#trigger-scope","title":"Trigger scope","text":"Triggers can be divided into two types:
Global trigger ( AI_StartTriggerScript ) trigger created using this function works in all worlds. A trigger is considered global by default if neither self
nor other
nor victim
has been provided for it. Local trigger ( AI_StartTriggerScriptEx) trigger created with this function only works in the world in which it was created. A trigger is considered local if it has been presented with at least one NPC in self
, other
or victim
(not null). If you want to create a trigger without linking it to any NPC, it is recommended to simply pass hero as self
to the trigger. "},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#saving","title":"Saving","text":"The plugin creates a new save archive to save the information of the triggers that does not conflict with any of the built-in save files.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/c_trigger/#searching","title":"Searching","text":"To search for a specific trigger, for example by NPC, the trigger external functions can be used.
// This way you can disable all triggers running on the `hero` instance\nvar C_Trigger trigger = FirstTrigger;\nvar C_Trigger trigger_saved;\nwhile (!Hlp_IsNULL(trigger))\n{\n trigger_saved = trigger;\n trigger = AI_GetNextTriggerBySelf(hero);\n trigger_saved.Enabled = false;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/","title":"Engine classes","text":""},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#engine-classes","title":"Engine classes","text":"zParserExtender implements various proxy classes that can be used to access game world objects.
Warning
It is not recommended to implement complex mechanics using these classes and functions. They are present as a simple backup option for accessing game world objects and for quick fixes.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_vob","title":"C_VOB","text":"This class represents basic pointer to a game world object.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_color","title":"C_Color","text":"Represents color in the RGBA format
class C_Color\n{\n var int R; // red channel value\n var int G; // green channel value\n var int B; // blue channel value\n var int A; // alpha channel value\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#zvec3","title":"zVEC3","text":"Represents 3D position in the world (float version for internal functions)
class zVEC3\n{\n var float X; // X coordinate\n var float Y; // Y coordinate\n var float Z; // Z coordinate\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_position","title":"C_Position","text":"Represents 3D position in the world
class C_Position\n{\n var int X; // X coordinate\n var int Y; // Y coordinate\n var int Z; // Z coordinate\n};\n
Externals: /// Returns the current position of the object in the world\n/// \n/// @param vob vob to ge the position of\n/// @return C_Position instance - position of the VOB\nfunc C_Position Vob_GetVobPosition( var C_Vob vob ) {};\n\n/// Sets the current position of the object in the world\n/// \n/// @param vob vob to get the position of\n/// @param pos new position of the vob\nfunc void Vob_SetVobPosition( var C_Vob vob, var C_Position pos ) {};\n
Note
The following classes define properties of C_VOB
objects or classes derived from it.
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_vob_data","title":"C_VOB_DATA","text":"Represents universal zCVob
class
class C_VOB_DATA\n{\n var string Name; // object name\n var float VisualAlpha; // object's transparency 0.0 - 1.0\n var int ShowVisual; // display the mode\n var int DrawBBox3D; // show objects bounding box\n var int VisualAlphaEnabled; // enables objects transparency\n var int PhysicsEnabled; // enables object's physics\n var int IgnoredByTraceRay; // allow any object collisions\n var int CollDetectionStatic; // allow collision with static world polygons\n var int CollDetectionDynamic; // allow collision with dynamic world objects\n var int CastDynShadow; // display shadow of the object\n var int LightColorStatDirty; // allow static lighting of the object\n var int LightColorDynDirty; // allow dynamic lighting of the object\n var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only)\n var int DontWriteIntoArchive; // turns of the serialization of this object to the save file \n};\n
Externals: /// Returns the universal data of the zCVob object\n///\n/// @param vob VOB to get the position of\n/// @return general vob data C_Vob_Data\nfunc C_Vob_Data Vob_GetVobData( var C_Vob vob ) {};\n\n/// Sets the universal data to a zCVob object\n///\n/// @param vob VOB to get the position of\n/// @param data general vob data C_Vob_Data\nfunc void Vob_SetVobData( var C_Vob vob, var C_Vob_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_light_data","title":"C_LIGHT_DATA","text":"Represents zCVobLight
objects
class C_LIGHT_DATA\n{\n var int R; // red light intensity\n var int G; // green light intensity\n var int B; // blue light intensity\n var int Range; // radius\n var int RangeInv; // \n var int RangeBackup; // \n var int RangeAniActFrame; // current light animation frame for the radius\n var int RangeAniFPS; // speed of light animation for the radius\n var int ColorAniActFrame; // current light animation frame for colour\n var int ColorAniFPS; // speed of light animation for colour\n var int SpotConeAngleDeg; // angle of cone light source\n var int IsStatic; // whether the source is static\n var int RangeAniSmooth; // [UNUSED]\n var int RangeAniLoop; // [UNUSED]\n var int ColorAniSmooth; // allows soft transitions between colours\n var int ColorAniLoop; // [UNUSED]\n var int IsTurnedOn; // whether the light source is on\n var int LightQuality; // source quality (when statically compiling light) (0 - high, 1 - medium, 2 - low)\n var int LightType; // type of source (at static light compilation) (0 - point, 1 - cone)\n};\n
Externals: /// Returns zCVobLight object data\n///\n/// @param vobLight vobLight object\n/// @return C_Light_Data of the light\nfunc C_Light_Data Vob_GetLightData( var C_Vob vobLight ) {};\n\n/// Sets the data of a zCVobLight object\n///\n/// @param vobLight object to apply the light data to\n/// @param data C_Light_Data light data to be set\nfunc void Vob_SetLightData( var C_Vob vobLight, var C_Light_Data data ) {};\n\n/// Clears the list of animation colours for the light source\n///\n/// @param vobLight light vob\nfunc void Vob_ClearLightAniList( var C_Vob vobLight ) {};\n\n/// Adds a color to the colour list\n///\n/// @param vobLight object to apply the colour to\n/// @param col colour to be applied\nfunc void Vob_AddLightAniColor( var C_Vob vobLight, var C_Color col ) {};\n\n/// Adds a color to the colour list\n///\n/// @param vobLight object to apply the colour to\n/// @param r red colour channel\n/// @param g green colour channel \n/// @param b blue colour channel\nfunc void Vob_AddLightAniColorRGB( var C_Vob vobLight,\n var int r,\n var int g,\n var int b ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_mob_data","title":"C_MOB_DATA","text":"Represents data for the used oCMOB object
class C_MOB_DATA\n{\n var string VisibleName; // name shown above the object\n var int Hitpoints; // number of hitpoints\n var int Damage; // damage the object can cause\n var int IsDestroyed; // if the object is destroyed\n var int Moveable; // whether the object can be moved\n var int Takeable; // whether the object can be taken\n var int FocusOverride; // if the object will redefine focus in combat mode\n var int SndMat; // object's material (0 - wood, 1 - stone, 2 - metal, 3 - skin, 4 - clay, 5 - glass)\n var string VisualDestroyed; // model when the object is destroyed\n var string OwnerStr; // name of the instance of the owner of the object\n var string OwnerGuildStr; // name of the guild of the object\n var int Owner; // instance of the owner\n var int OwnerGuild; // guild instance\n var int FocusNameIndex; // the script string of the displayed name\n};\n
/// Returns the data of the oCMOB object\n///\n/// @param mob oCMOB object\n/// @return mob data\nfunc C_Mob_Data Vob_GetMobData( var C_Vob mob ) {};\n\n/// Sets the data of the oCMOB object\n///\n/// @param mob oCMOB object\n/// @param data C_Mob_Data to be set \nfunc void Vob_SetMobData( var C_Vob mob, var C_Mob_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_mobinter_data","title":"C_MOBINTER_DATA","text":"Represents data for the interactive object oCMobInter
class C_MOBINTER_DATA\n{\n var string TriggerTarget; // object name which will be triggered by OnTrigger\n var string UseWithItem; // name of the object instance that is needed for interaction\n var string Sceme; // name of the scene that corresponds to the object and character animations\n var string ConditionFunc; // scripting condition under which the interaction can be performed\n var string OnStateFuncName; // the name pattern of the functions that will be called when the object changes the state\n var int State; // the current state of the object\n var int State_num; // number of object's states\n var int State_target // current state of the object\n var int Rewind; // prohibits object updating\n var int MobStateAni; // current animation of the object\n var int NpcStateAni; // current character animation\n};\n
/// Returns the data of the oCMobInter object\n///\n/// @param mobInter oCMobInter object\n/// @return MobInter_Data of the object\nfunc MobInter_Data Vob_GetMobInterData( var C_Vob mobInter ) {};\n\n/// Sets the data of the oCMobInter object\n///\n/// @param mobInter oCMobInter object\n/// @param data MobInter_Data of the object\nfunc void Vob_SetMobInterData( var C_Vob mobInter, var C_MobInter_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/classes/helperclasses/#c_moblockable_data","title":"C_MOBLOCKABLE_DATA","text":"Represents data for the locked interactive object oCMobLockable
class C_MOBLOCKABLE_DATA\n{\n var int Locked; // whether the object is locked\n var int AutoOpen; // [UNUSED]\n var int PickLockNr; // current rotation number \n var string KeyInstance; // key instance name for the object\n var string PickLockStr; // combination to open the object (\"LRRLR\")\n};\n
/// Returns the data of the oCMobLockable object\n///\n/// @param mobLock oCMobLockable object\n/// @param data MobInter_Data of the object\nfunc C_MobLockable_Data Vob_GetMobInterData( var C_Vob mobLock ) {};\n\n/// Sets the data of the oCMobLockable object\n///\n/// @param mobLock oCMobLockable object\n/// @param data C_MobLockable_Data of the object\nfunc void Vob_SetMobInterData( var C_Vob mobLock, var C_MobLockable_Data data ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/","title":"Daedalus Injection","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/#daedalus-injection","title":"Daedalus Injection","text":"Script injection is a process of injecting Daedalus scripts on runtime without the need to recompile the scripts. This is essential for Union plugins that need to alter the scripts in a certain way, either for hotfixes or just for testing scripts without the need to recompile the whole .dat
file.
To inject a script, simply put a .d
or .src
file in Gothic/System/Autorun
directory and run the game.
Tip
Automatic injection does not extend to nested directories in the Autorun directory directly, but you can put a .src
file into Autorun
directory and the rest into a subdirectory to keep a cleaner structure.
Scripts in subdirectories can be accessed in two ways
They are specified in a .src
file The script file is an API script "},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/#api-script","title":"API script","text":"API scripts are .d
files placed in Autorun
subdirectories and are used as a dependency. It is assumed that the API script is not called on its own (or from a .src
) file, but is called using the dependency keyword After
in one of the injected script files' META block.
These scripts are meant to contain ready-made solution that need to be used by many other scripts as a dependency.
Warning
If the file specified in the After
tag in the META block does not exist, the current file will not be parsed and injected since the dependency is missing, and it would fail. Due to this it is best to ship the dependency in the Autorun directory even if it comes from a different plugin.
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/","title":"Hooking Daedalus","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#hooking-daedalus","title":"Hooking Daedalus","text":"Daedalus hooking is one of the most powerful features of this plugin. Hooking is a mechanism that allows you to replace any scripted object with a new one. To do this, you must define a new object with the same type, name and in the same namespace.
Hook/replacement will be performed only if the MergeMode
setting is set to true for the current script in the META block or in the parameter of the same name in the .ini
file of the mod.
Warning
If you forget to turn on the MergeMode
, the compilation will fail with the redefinition error.
When an object (instance, function or variable) is hooked/replaced, the original one is available under the same name with the _old
suffix (PC_Hero
-> PC_Hero_old
). This allows you to refer to the old object.
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#function-hook-example","title":"Function hook example","text":"func void ZS_Attack_Loop()\n{\n // if the enemy is a player and has no weapon, then\n // also sheath the weapon.\n if (Npc_IsPlayer(other) && !Npc_HasReadiedWeapon(other))\n {\n return LOOP_END;\n };\n\n // otherwise call the original function\n return ZS_Attack_Loop_Old();\n};\n
This kind of substitution works for instances and variables too.
Warning
While hooking an instances, you have to take care not to call the prototype. Prototype should be always changed back to the original class.
This is wronginstance pc_hero(Npc_Default)\n{\n pc_hero_old();\n name = \"Pepe\";\n};\n
This leads to a double call of prototype Npc_Default
which is considered an unsafe practice with undefined behaviour. The correct way is to call it like this:
instance pc_hero(C_NPC) // no prototype Npc_Default\n{\n pc_hero_old();\n name = \"Pepe\";\n}; \n
This way the prototype is called in the original function pc_hero_old()
and not for the second time when creating the new hooked instance."},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/#dialogue-hook-example","title":"Dialogue hook example","text":"The hooking mechanism is designed to introduce new dialogues into the game as well as replacing old ones with hooks. The scripter can create new merchants, quests, dialogues, as well as attach svm phrases to them.
All new or replaced dialogues will immediately become available, including from saves. In the event that new dialogs are disabled (plugin or script removed), the engine will continue to keep them in the save file, which will allow the dialogs to return at any time with the same state they were in the last time.
Warning
Currently not working as intended (I think). The old dialogue is still used and as a result you will end up with both the old and the new dialogue (unless you edit the old condition function).
instance DIA_XARDAS_HELLO(C_INFO)\n{\n DIA_XARDAS_HELLO_old();\n important = FALSE;\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/meta/","title":"META block","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/meta/#meta-block","title":"META block","text":"The META block is optional. If it is specified, it has to be the very first thing in the file without any indent or a comment above it.
Syntax:
META\n{\n Parser // specifies into which compiled file the scripts are going to be injected\n /*\n Code Name DAT file\n --- ------ -------\n Game parser Gothic.dat\n SFX parserSoundFX SFX.dat\n PFX parserParticleFX ParticleFX.dat\n VFX parserVisualFX VisualFX.dat\n Camera parserCamera Camera.dat\n Menu parserMenu Menu.dat\n Music parserMusic Music.dat\n */\n MergeMode // 0 - if conflict occurs = compilation error, 1 - if conflict occurs = hook\n Engine // comma separated list of engines for which the scripts will be injected \n /*\n Code Engine Human readable name\n --- ----- -----------------------\n G1 Gothic I Gothic I Classic\n G1A Gothic Sequel Gothic I Addon <3\n G2 Gothic II Gothic II Classic\n G2A Gothic II NoTR Gothic II Addon\n */\n\n NativeWhile // use native while\n Namespace // namespace of this script file\n Using // comma separated list of namespaces, that are considered local for this script file\n Mod // specify for which mod should this code be injected\n After // comma separated list of scripts, after which this script should be parsed\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/","title":"Other functions of the extender","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#other-functions-of-the-extender","title":"Other functions of the extender","text":""},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#ini-parameters","title":"ini parameters","text":"The choice of ini file depends on how the game was launched. If it was launched from Gothic.exe, then the parameters will be read from SystemPack.ini
. If it was launched through GothicStarter.exe, then they will be read from the ini of the mod.
[zParserExtender]\nLoadScript(obsolete) =\n;specifies a parser-script format script to run the scripts. The parameter is currently invalid.\n\nMergeMode = True\n;specifies whether injections will produce hooks.\n\nCompileDat = False\n;Determines if a copy of DAT file which has been modified by injection will be created.\n\nCompileOU = False\n;determines if a copy of an injection-modified OU file will be created.\n\nNativeWhile = False\n;Determines if a WHILE loop will be compiled. Defaults to False (for Ninja compatibility).\n\nMessagesLevel = 1\n;sets the output level. The higher the level, the more information will be printed to the debug console.\n\nStringIndexingMode = -1\n;defines string indexing mode (see string indexing). Default value is -1.\n;Default = -1 - The default mode for the moment is Repair mode.\n;Disabled = 0 - Do nothing with the indices.\n;TopSymbol = 1 - The plugin finds the uppermost unnamed string and sets a counter for it.\n;Repair = 2 - The plugin goes through the whole string table and, if the indexing order is broken, puts the correct names. The counter is set on the basis of the search.\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#marvin-console-commands","title":"MARVIN console commands","text":"zParserExtender adds console commands that save copies of the .dat
files with the injected code.
Warning
If the mod uses Ikarus, the CompileDat
option (in the .ini
file) should be used since a fatal error may occur when using the command.
Parser SaveDat OU - exports OU.Edited.bin\nParser SaveDat Game - exports Gothic.Edited.dat\nParser SaveDat SFX - exports SFX.Edited.dat\nParser SaveDat PFX - exports ParticleFX.Edited.dat\nParser SaveDat VFX - exports VisualFX.Edited.dat\nParser SaveDat Camera - exports Camera.Edited.dat\nParser SaveDat Menu - exports Menu.Edited.dat\nParser SaveDat Music - exports Music.Edited.dat\nParser Export Stringlist - exports the full string table to Scripts\\Exports\\StringList.d\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#launch-options","title":"Launch options","text":"Command line parameters can be passed to the game's exe via the command line or using GothicStarter_Mod.
zReparse_OU - parses and creates OU.bin\nzReparse_Game - parses and creates Gothic.dat\nzReparse_SFX - parses and creates SFX.dat\nzReparse_PFX - parses and creates ParticleFX.dat\nzReparse_VFX - parses and creates VisualFX.dat\nzReparse_Camera - parses and creates Camera.dat\nzReparse_Menu - parses and creates Menu.dat\nzReparse_Music - parses and creates Music.dat\n
Note
If you want to compile OU, you also have to include the Game parameter
-zReparse_Game -zReparse_OU
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#const-array-access","title":"Const array access","text":"The original zParser doesn't allow direct access to const string
arrays. zParserExtender allows you to do so.
Example:
func event GameInit()\n{\n Hlp_MessageBox(TXT_INV_CAT[4]); // Prints \"Artifacts\"\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/daedalus_injection/other/#other-engine-fixes","title":"Other engine fixes","text":" When creating an item instance, the instance is placed into the global item
instance On DAT file load, the engine restores the original symbol hierarchy When loading a save, the engine now skips unknown symbols, instead of crashing "},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/","title":"Sign post teleportation","text":""},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#sign-post-teleportation","title":"Sign post teleportation","text":"This is a short \"problem-solving\" example, where we try to demonstrate the power of Daedalus injection using zParserExtender. GaroK asked me if there is a way to teleport to all the sign posts in Khorinis to gather information for a Gothic wiki article. The goal is to introduce a function that will teleport you to every signpost in Khorinis with the press of a button.
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#the-problem","title":"The problem","text":"In ZenGin you can teleport to named game objects with the goto vob {vobname}
command. But since the signposts do not have a vobname defined, I had to figure out a different approach.
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#ascii-zen","title":"ASCII ZEN","text":"We want to get all the signposts position from Khorinis. The game world was loaded into one of the available world editor, I found one of the signposts and noted the visual
which dictates the model of the in-game object nw_misc_sign_01.3DS
. Alternatively, you can find the standard vanilla objects from both games on this website. Next, the world was saved as a ASCII ZEN
format. This allows us to write a macro to search for all instances of objects with a specific visual and extract the position vector.
One signpost object[% oCMOB:zCVob 47105 317]\n pack=int:0\n presetName=string:\n bbox3DWS=rawFloat:7564.8291 127.361191 -80.5309067 7611.52441 377.422913 1.67681122 \n trafoOSToWSRot=raw:73e1673f9c4ec33b15efd8be4465d7bba0fe7f3f30ea7137e5edd83eecaa353bb7e2673f\n trafoOSToWSPos=vec3:7588.17627 252.391052 -39.4283791\n vobName=string:\n visual=string:NW_MISC_SIGN_01.3DS\n showVisual=bool:1\n visualCamAlign=enum:0\n visualAniMode=enum:0\n visualAniModeStrength=float:0\n vobFarClipZScale=float:1\n cdStatic=bool:1\n cdDyn=bool:1\n staticVob=bool:1\n dynShadow=enum:0\n zbias=int:0\n isAmbient=bool:0\n [visual zCProgMeshProto 53505 318]\n []\n [ai % 0 0]\n []\n focusName=string:MOBNAME_INCITY02\n hitpoints=int:10\n damage=int:0\n moveable=bool:0\n takeable=bool:0\n focusOverride=bool:0\n soundMaterial=enum:0\n visualDestroyed=string:\n owner=string:\n ownerGuild=string:\n isDestroyed=bool:0\n[]\n
Tip
You can also see that the focusName
has a MOBNAME_INCITY02
string constant. This constant is defined in the scripts and its content is used as the focus name.
const string MOBNAME_INCITY02 = \"To Marketplace\";\n
"},{"location":"zengin/scripts/extenders/zparserextender/examples/signposts/#the-injectable-script","title":"The injectable script","text":"As it is an injectable script, we have to specify the META
tag. Lets tell zParserExtender to insert this code into the game parser.
META\n{\n Parser = Game\n};\n
We want to teleport the player and for this we will need the C_Position
and C_Vob_Data
classes. class C_Position\n{\n var int X; // X coordinate\n var int Y; // Y coordinate\n var int Z; // Z coordinate\n};\n\nclass C_VOB_DATA\n{\n var string Name; // object name\n var float VisualAlpha; // object's transparency 0.0 - 1.0\n var int ShowVisual; // display the mode\n var int DrawBBox3D; // show objects bounding box\n var int VisualAlphaEnabled; // enables objects transparency\n var int PhysicsEnabled; // enables object's physics\n var int IgnoredByTraceRay; // allow any object collisions\n var int CollDetectionStatic; // allow collision with static world polygons\n var int CollDetectionDynamic; // allow collision with dynamic world objects\n var int CastDynShadow; // display shadow of the object\n var int LightColorStatDirty; // allow static lighting of the object\n var int LightColorDynDirty; // allow dynamic lighting of the object\n var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only)\n var int DontWriteIntoArchive; // turns of the serialization of this object to the save file \n};\n
It turns out there is 54 instances of objects with the desired visual. Let us define const int NUM_OF_SIGNS = 54
and a const int MAX_COORDS = 3 * NUM_OF_SIGNS
- we will store 3 times 54 integers - for every signpost a x
, y
and z
coordinate. And lastly a const int
array containing all the positions. // Number of signs we want to jump to\nconst int NUM_OF_SIGNS = 54;\nconst int MAX_COORDS = 3 * NUM_OF_SIGNS;\n\nconst int sign_coordinates[MAX_COORDS] = {\n 11974, 309, 6815,\n 12024, 310, 6778,\n 12411, 1668, -22495,\n 19491, 1281, 1669,\n 19563, 1281, 1687,\n 20294, 2058, 12487,\n 20324, 2058, 12419,\n 21917, 2900, -22751,\n 2600, -57, -4351,\n 26695, 2419, 4308,\n 26770, 2418, 4319,\n 26978, 2937, 6130,\n 27015, 2936, 6104,\n 27049, 2937, 6159,\n 2964, 2142, 14424,\n 31383, 3896, 4699,\n 31427, 3896, 4640,\n 35368, 3870, -4374,\n 35435, 3870, -4355,\n 35437, 3871, -4399,\n 36205, 3333, -27186,\n 37774, 3875, -501,\n 37812, 3874, -469,\n 37849, 3874, -512,\n 38291, 3732, -6699,\n 39276, 3926, -3357,\n 39307, 3924, -3313,\n 39351, 3924, -3359,\n 39435, 4350, 10902,\n 39458, 4350, 10827,\n 40932, 3861, -3054,\n 42454, 2838, -19437,\n 5297, 387, -2145,\n 5358, 387, -2184,\n 5362, 387, -2128,\n 54006, 1723, -10316,\n 54035, 1723, -10387,\n 551, -62, -1820,\n 61080, 2132, -11622,\n 61155, 2132, -11625,\n 6408, 392, 3598,\n 6432, 393, 3652,\n 7000, 387, -1482,\n 73439, 3341, -11307,\n 7588, 252, -39,\n 7590, 252, -109,\n 7642, 253, -83,\n 7713, 387, -4782,\n 7758, 386, -4775,\n 7776, 388, -4811,\n 8154, 1206, -17022,\n 8855, 395, -2402,\n 9704, 393, 5129,\n 9738, 392, 5108\n};\n
Next define a built in event GameLoop
function, to check for a pressed key. If the key U
is pressed, the jump_to_sign
function is called. // check for pressed U button every frame\nfunc event GameLoop()\n{\n // if U is toggled, run the function\n if (Hlp_KeyToggled(KEY_U))\n {\n jump_to_sign();\n };\n};\n
Let's look at the jump_to_sign
function now. This function is called on every U
key press and goes through all the signposts and teleports the player to them. At the start of the function we check if the index is not out of bounds and if it is, sets it back to 0 and starts over.
// if we reached the end, start over\n if (tp_index >= NUM_OF_SIGNS)\n {\n tp_index = 0;\n };\n
Notice the use of Str_Format
function for the formatted output. // give information to the player\nPrint(Str_Format(\"Sign %i/%i\", tp_index+1, NUM_OF_SIGNS));\n\nvar C_Position pos; pos = Vob_GetVobPosition(hero);\nvar C_Vob_Data data; data = Vob_GetVobData(hero);\n
Daedalus does not allow array access with variables (only constants and literals). To access the coordinate array we use a selection of parser functions. Firstly we get the game parser ID. Then we can use the Par_GetSymbolValueIntArray
to access the sign_coordinates
array and assign the coordinates to the pos
variable. // get parser ID for the GAME parser\nvar int game_par_id; game_par_id = Par_GetParserID(\"game\");\n\n// get parser ID of the array\nvar int arr_id; arr_id = Par_GetSymbolID(game_par_id ,\"sign_coordinates\");\n\n// access the coordinates from above array\npos.x = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 ); \npos.y = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 + 1);\npos.z = Par_GetSymbolValueIntArray(game_par_id ,arr_id ,tp_index * 3 + 2);\n
And now comes the big trick. If you try to just change the position the dynamic and static collision is going to stop you at the first wall, tree or a mountain. To disable it, we can use the C_Vob_Data
helper class, get players data, and disable both the static a dynamic collision. First we create a backup of the values just so we can restore them back after the teleport. // backup original collision detection\nvar int dyn; dyn = data.CollDetectionDynamic;\nvar int stat; stat = data.CollDetectionStatic;\n\n// turn off collision detection \ndata.CollDetectionDynamic = 0;\ndata.CollDetectionStatic = 0;\n
Let us apply the changed data to the player and edit the position. // apply the edited data to player\nVob_SetVobData(hero, data);\n\n// move the player \nVob_SetVobPosition(hero, pos);\n
Restore the collision detection data from the backup we made and set it. // restore collision detection\ndata.CollDetectionDynamic = dyn;\ndata.CollDetectionStatic = stat;\n\n// apply the edited data to player\nVob_SetVobData(hero, data);\n
Finally, we advance the index to jump to another signpost. // advance the index\ntp_index += 1;\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/","title":"AI - functions for working with AI","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai---functions-for-working-with-ai","title":"AI - functions for working with AI","text":"Functions to work with the new C_Trigger
class and NPC's AI queue.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_callscript","title":"AI_CallScript
","text":"AI_CallScript
Adds a funcName
function call to the AI queue
func void AI_CallScript(var string funcName,\n var C_NPC slf,\n var C_NPC oth) {};\n
funcName
- name of the function to be called slf
- will be inserted into global self
instance oth
- will be inserted into global other
instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_starttriggerscript","title":"AI_startTriggerScript
","text":"AI_startTriggerScript
Creates a trigger script that calls function funcName
once every interval
in milliseconds
func C_Trigger AI_startTriggerScript(var string funcName, var int interval) {};\n
funcName
- name of the function to be called interval
- call period in milliseconds return
- created C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_starttriggerscriptex","title":"AI_startTriggerScriptEx
","text":"AI_startTriggerScriptEx
Extended version call - Creates a trigger script, that calls function funcName
once every interval
in milliseconds also updates the self
, other
and victim
global instances based on slf
, oth
and vct
parameters respectively
func C_Trigger AI_startTriggerScriptEx( var string funcName,\n var int interval,\n var C_NPC slf,\n var C_NPC oth,\n var C_NPC vct) {};\n
funcName
- name of the function to be called interval
- call period in milliseconds slf
- will be inserted into global self
instance oth
- will be inserted into global other
instance vct
- will be inserted into global victim
instance return
- created C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerbyid","title":"AI_GetTriggerByID
","text":"AI_GetTriggerByID
Returns a C_Trigger instance from the array of active triggers by the array index ID
func C_Trigger AI_GetTriggerByID(var int ID) {};\n
ID
- array id return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggersnum","title":"AI_GetTriggersNum
","text":"AI_GetTriggersNum
Returns the number of active C_Trigger scripts
func int AI_GetTriggersNum() {};\n
return
- number of active C_Trigger scripts "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggernpc","title":"AI_GetTriggerNPC
","text":"AI_GetTriggerNPC
Returns the npc associated with the C_Trigger script based on the ID selfID = 0; otherID = 1; victimID = 2;
func C_NPC AI_GetTriggerNPC(var C_Trigger trigger, var int npcID) {};\n
trigger
- C_Trigger script npcID
- NPC id return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerfunc","title":"AI_GetTriggerFunc
","text":"AI_GetTriggerFunc
Returns the function associated with the specified C_Trigger
func func AI_GetTriggerFunc(var C_Trigger trigger) {};\n
trigger
- C_Trigger script return
- trigger function "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_gettriggerfuncname","title":"AI_GetTriggerFuncName
","text":"AI_GetTriggerFuncName
Returns the function name of a function associated with the specified C_Trigger
func string AI_GetTriggerFuncName(var C_Trigger trigger) {};\n
trigger
- C_Trigger script return
- active C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyfunc","title":"Ai_GetNextTriggerByFunc
","text":"Ai_GetNextTriggerByFunc
Returns the next trigger in the active trigger array based on the trigger function, starting on the startTrigger
trigger
func C_Trigger Ai_GetNextTriggerByFunc(var C_Trigger startTrigger, var func function) {};\n
startTrigger
- C_Trigger script to start the search from function
- function to be matched return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyfuncname","title":"Ai_GetNextTriggerByFuncName
","text":"Ai_GetNextTriggerByFuncName
Returns the next trigger in the active trigger array based on the trigger function name, starting on the startTrigger
trigger
func C_Trigger Ai_GetNextTriggerByFuncName(var C_Trigger startTrigger, var string functionName) {};\n
startTrigger
- C_Trigger script to start the search from functionName
- name of a function to be matched return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyself","title":"Ai_GetNextTriggerBySelf
","text":"Ai_GetNextTriggerBySelf
Returns the next trigger in the active trigger array based on the self
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerBySelf(var C_Trigger startTrigger, var C_NPC self) {};\n
startTrigger
- C_Trigger script to start the search from self
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyother","title":"Ai_GetNextTriggerByOther
","text":"Ai_GetNextTriggerByOther
Returns the next trigger in the active trigger array based on the other
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerByOther(var C_Trigger startTrigger, var C_NPC other) {};\n
startTrigger
- C_Trigger script to start the search from other
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbyvictim","title":"Ai_GetNextTriggerByVictim
","text":"Ai_GetNextTriggerByVictim
Returns the next trigger in the active trigger array based on the victim
trigger parameter, starting on the startTrigger
instance set in the trigger
func C_Trigger Ai_GetNextTriggerByVictim( var C_Trigger startTrigger, var C_NPC victim ) {};\n
startTrigger
- C_Trigger script to start the search from victim
- C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/ai/#ai_getnexttriggerbynpcs","title":"Ai_GetNextTriggerByNPCs
","text":"Ai_GetNextTriggerByNPCs
Returns the next trigger in the active trigger array based on all the NPCs set in the trigger script self
, other
and victim
, starting on the startTrigger
instance set in the trigger
func c_trigger Ai_GetNextTriggerByNPCs( var C_Trigger startTrigger,\n var C_NPC self,\n var C_NPC other,\n var C_NPC victim) {};\n
startTrigger
- C_Trigger script to start the search from self
- self C_NPC instance other
- other C_NPC instance victim
- victim C_NPC instance return
- C_Trigger instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/","title":"CAST - data type conversion functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast---data-type-conversion-functions","title":"CAST - data type conversion functions","text":"External functions for data type conversion and pointer casting.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertoinstance","title":"Cast_PointerToInstance
","text":"Cast_PointerToInstance
Converts memory address (pointer) to an instance
func instance Cast_PointerToInstance(var int address) {};\n
address
- object pointer return
- instance of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instancetopointer","title":"Cast_InstanceToPointer
","text":"Cast_InstanceToPointer
Converts instance to a memory address (pointer)
func int Cast_InstanceToPointer( var instance object) {};\n
object
- object instance return
- memory address (pointer) of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertonpc","title":"Cast_PointerToNpc
","text":"Cast_PointerToNpc
Casts memory address (pointer) to an NPC
func C_NPC Cast_PointerToNpc( var int address) {};\n
address
- npc pointer return
- NPC instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_pointertoitem","title":"Cast_PointerToItem
","text":"Cast_PointerToItem
Casts memory address (pointer) to an Item
func C_ITEM Cast_PointerToItem( var int address) {};\n
address
- item pointer return
- Item instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceisnpc","title":"Cast_InstanceIsNpc
","text":"Cast_InstanceIsNpc
Checks whether object is an NPC
func int Cast_InstanceIsNpc( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceisitem","title":"Cast_InstanceIsItem
","text":"Cast_InstanceIsItem
Checks whether object is an Item
func int Cast_InstanceIsItem( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_instanceismob","title":"Cast_InstanceIsMob
","text":"Cast_InstanceIsMob
Checks whether object is an MOB
func int Cast_InstanceIsMob( var instance object) {};\n
object
- object to check return
- TRUE
or FALSE
"},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getinstanceindex","title":"Cast_GetInstanceIndex
","text":"Cast_GetInstanceIndex
Returns symbolID of the object, returns -1 when not found
func int Cast_GetInstanceIndex( var instance object) {};\n
object
- instance of an object return
- symbol table index, -1 when not found "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getclassid","title":"Cast_GetClassID
","text":"Cast_GetClassID
Returns the class identifier of a class by its name
func int Cast_GetClassID( var string className ) {};\n
className
- name of the class return
- class identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_getvobclassid","title":"Cast_GetVobClassID
","text":"Cast_GetVobClassID
Returns class identifier of the zCObject vob class
func int Cast_GetVobClassID( var instance object ) {};\n
object
- object instance return
- class zCObject identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/cast/#cast_checkvobclassid","title":"Cast_CheckVobClassID
","text":"Cast_CheckVobClassID
Checks if the classId class is the parent class of the object
func int Cast_CheckVobClassID( var int classId, var instance object ) {};\n
classId
- class identifier, from Cast_GetClassID function object
- object instance return
- class zCObject identifier "},{"location":"zengin/scripts/extenders/zparserextender/externals/events_vars/","title":"Event functions and variables","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/events_vars/#event-functions-and-variables","title":"Event functions and variables","text":"On top of external functions, zParserExtender also adds these event functions and constants.
/// Every event function with this name is executed once every frame\nfunc event GameLoop() {};\n\n/// Every event function with this name is executed once on game init\nfunc event GameInit() {};\n\n/// empty instance\nconst instance null;\n\n/// not a number floating point constant\nconst float NaN;\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/","title":"HLP - help functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp---help-functions","title":"HLP - help functions","text":"Helper functions generally used for safety checks, to get specific information from the engine or to interface with the configuration .ini
files.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_hasfocusvob","title":"Hlp_HasFocusVob
","text":"Hlp_HasFocusVob
Returns TRUE
, if a specified NPC has a Vob in focus
func int Hlp_HasFocusVob( var C_NPC npc ) {};\n
npc
- NPC return
- TRUE
if npc has a focus Vob, FALSE
if it does not "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getfocusvob","title":"Hlp_GetFocusVob
","text":"Hlp_GetFocusVob
Returns NPC's focus Vob
func instance Hlp_GetFocusVob( var C_NPC npc ) {};\n
npc
- NPC return
- focus vob "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getfocusvobname","title":"Hlp_GetFocusVobName
","text":"Hlp_GetFocusVobName
Returns the name of NPC's focus vob
func string Hlp_GetFocusVobName( var C_NPC npc ) {};\n
npc
- NPC return
- focus vob name "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getstringlength","title":"Hlp_GetStringLength
","text":"Hlp_GetStringLength
Returns the length of a specified string
func int Hlp_GetStringLength( var string str ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#isnan","title":"IsNAN
","text":"IsNAN
Checks whether floating point number is valid
func int IsNAN( var float value ) {};\n
return
- TRUE
if value
is NaN, FALSE
if value
is a valid floating point number "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_keytoggled","title":"Hlp_KeyToggled
","text":"Hlp_KeyToggled
Checks whether key
is toggled
func int Hlp_KeyToggled( var int key ) {};\n
key
- key code return
- TRUE
if key is toggled, FALSE
if key is not toggled "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_keypressed","title":"Hlp_KeyPressed
","text":"Hlp_KeyPressed
Checks whether key
is pressed
func int Hlp_KeyPressed( var int key ) {};\n
key
- key code return
- TRUE
if key is pressed, FALSE
if key is not pressed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_logicalkeytoggled","title":"Hlp_LogicalKeyToggled
","text":"Hlp_LogicalKeyToggled
Checks whether logical key
is toggled
func int Hlp_LogicalKeyToggled( var int key ) {};\n
key
- key code return
- TRUE
if key is toggled, FALSE
if key is not toggled "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_gameonpause","title":"Hlp_GameOnPause
","text":"Hlp_GameOnPause
Checks whether the game is paused
func int Hlp_GameOnPause() {};\n
return
- TRUE
if the game is paused, FALSE
if the game is not paused "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_messagebox","title":"Hlp_MessageBox
","text":"Hlp_MessageBox
Opens a message box with a specified message
func void Hlp_MessageBox( var string message ) {};\n
message
- message to be printed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_printconsole","title":"Hlp_PrintConsole
","text":"Hlp_PrintConsole
Prints a message to the Union debug console
func void Hlp_PrintConsole(var string message) {};\n
message
- message to be printed "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_optionisexists","title":"Hlp_OptionIsExists
","text":"Hlp_OptionIsExists
Checks whether the entry
in section
in .ini
file optName
exists
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func int Hlp_OptionIsExists(var string optName, var string section, var string entry) {};\n
optName
- the .ini
file section
- settings section like [GAME]
entry
- one setting entry like playLogoVideos
return
- TRUE
if the option exists, FALSE
if the option does not exist "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionint","title":"Hlp_ReadOptionInt
","text":"Hlp_ReadOptionInt
Read an integer value from specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func int Hlp_ReadOptionInt(var string optName, var string section, var string entry, var int default) {};\n
optName
- the .ini
file section
- settings section like [GAME]
entry
- one setting entry like playLogoVideos
default
- default value - if the value is empty return
- the option value "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionfloat","title":"Hlp_ReadOptionFloat
","text":"!!! function \"`Hlp_ReadOptionFloat`\"\nRead a floating point value from specified `.ini` file, section and entry.\n\n`optName` values\n\n- `#!dae \"Gothic\"`\n- `#!dae \"Mod\"`\n- `#!dae \"SystemPack\"`\n\n```dae\nfunc float Hlp_ReadOptionFloat(var string optName, var string section, var string entry, var float default) {};\n```\n\n- `optName` - the `.ini` file\n- `section` - settings section like `[INTERFACE]`\n- `entry` - one setting entry like `scale`\n- `default` - default value - if the value is empty\n- `return` - the option value\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_readoptionstring","title":"Hlp_ReadOptionString
","text":"Hlp_ReadOptionString
Read a string value from specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func string Hlp_ReadOptionString(var string optName, var string section, var string entry, var string default) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
default
- default value - if the value is empty return
- the option value "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionint","title":"Hlp_WriteOptionInt
","text":"Hlp_WriteOptionInt
Writes an integer value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionInt(var string optName, var string section, var string entry, var int value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionfloat","title":"Hlp_WriteOptionFloat
","text":"Hlp_WriteOptionFloat
Writes a floating point value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionFloat(var string optName, var string section, var string entry, var float value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_writeoptionstring","title":"Hlp_WriteOptionString
","text":"Hlp_WriteOptionString
Writes a string value to specified .ini
file, section and entry.
optName
values
\"Gothic\"
\"Mod\"
\"SystemPack\"
func void Hlp_WriteOptionString(var string optName, var string section, var string entry, var string value) {};\n
optName
- the .ini
file section
- settings section like [INTERFACE]
entry
- one setting entry like scale
value
- value to be written "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_getsteampersonalname","title":"Hlp_GetSteamPersonalName
","text":"Hlp_GetSteamPersonalName
Returns the name of the current Steam user Returns empty string when not run with Steam
func string Hlp_GetSteamPersonalName() {};\n
return
- string containing the Steam username, or an empty string "},{"location":"zengin/scripts/extenders/zparserextender/externals/hlp/#hlp_doevent","title":"Hlp_DoEvent
","text":"Hlp_DoEvent
Calls every event function with the name funcName
.
func void Hlp_DoEvent(var string funcName) {};\n
funcName
- name of the event function to be called (all of them). "},{"location":"zengin/scripts/extenders/zparserextender/externals/log/","title":"Log functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log-functions","title":"Log functions","text":"As discussed on Inside Gothic, vanilla Gothic has no way of getting the status of a quest. These functions implement that functionality.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log_gettopicstatus","title":"Log_GetTopicStatus
","text":"Log_GetTopicStatus
Returns the status of diary topic
-1
- Not found 0
- Free 1
- Running 2
- Success 3
- Failure 4
- Obsolete func int Log_GetTopicStatus(var string topic) {};\n
topic
- name of the topic return
- topic status "},{"location":"zengin/scripts/extenders/zparserextender/externals/log/#log_gettopicsection","title":"Log_GetTopicSection
","text":"Log_GetTopicSection
Returns the topic the diary topic is in
-1
- Not found 0
- Missions 1
- Notes 2
- All func int Log_GetTopicSection(var string topic) {};\n
topic
- name of the topic return
- topic section "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/","title":"MDL - model functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl---model-functions","title":"MDL - model functions","text":"Functions to tweak animation and other model related settings.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_getanimationindex","title":"Mdl_GetAnimationIndex
","text":"Mdl_GetAnimationIndex
Returns animation's index for specified NPC based on animation's name
func int Mdl_GetAnimationIndex( var C_NPC npc, var string ani_name ) {};\n
npc
- NPC with the animation ani_name
- name of the animation in uppercase return
- animation index "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_getanimationname","title":"Mdl_GetAnimationName
","text":"Mdl_GetAnimationName
Returns animation's name for specified NPC based on animation's index
func string Mdl_GetAnimationName( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- animation name "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_animationisexists","title":"Mdl_AnimationIsExists
","text":"Mdl_AnimationIsExists
Checks whether animation exists
func int Mdl_AnimationIsExists( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- animation name "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_animationisactive","title":"Mdl_AnimationIsActive
","text":"Mdl_AnimationIsActive
Checks whether animation is active (whether it is currently played)
func int Mdl_AnimationIsActive( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index return
- TRUE
if the animation is playing, FALSE
if it is not playing "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setallanimationsfps","title":"Mdl_SetAllAnimationsFPS
","text":"Mdl_SetAllAnimationsFPS
Set framerate for all animations
func void Mdl_SetAllAnimationsFPS( var C_NPC npc, var float fps ) {};\n
npc
- NPC with the animation fps
- framerate "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetallanimationsfps","title":"Mdl_ResetAllAnimationsFPS
","text":"Mdl_ResetAllAnimationsFPS
Reset framerate for all animations to default value
func void Mdl_ResetAllAnimationsFPS( var C_NPC npc ) {};\n
npc
- NPC with the animation "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setanimationfps","title":"Mdl_SetAnimationFPS
","text":"Mdl_SetAnimationFPS
Set framerate for animation specified by animation index
func void Mdl_SetAnimationFPS( var C_NPC npc, var int ani_index, var float fps ) {};\n
npc
- NPC with the animation ani_index
- animation index fps
- framerate "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetanimationfps","title":"Mdl_ResetAnimationFPS
","text":"Mdl_ResetAnimationFPS
Reset framerate to default for animation specified by animation index
func void Mdl_ResetAnimationFPS( var C_NPC npc, var int ani_index ) {};\n
npc
- NPC with the animation ani_index
- animation index "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setvisible","title":"Mdl_SetVisible
","text":"Mdl_SetVisible
Set NPCs visibility
func void Mdl_SetVisible( var C_NPC npc, var int isVisible ) {};\n
npc
- specified NPC isVisible
- TRUE
- visible, FALSE
- invisible "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_applyoverlaymds_atfirst","title":"Mdl_ApplyOverlayMds_AtFirst
","text":"Mdl_ApplyOverlayMds_AtFirst
Applies or moves existing overlay to the top of the list
func void Mdl_ApplyOverlayMds_AtFirst( var string mdsName ) {};\n
mdsName
- name of the overlay "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_setnpcspeedmultiplier","title":"Mdl_SetNpcSpeedMultiplier
","text":"Mdl_SetNpcSpeedMultiplier
Sets a multiplier for animation speed 1.0 = 100% speed (normal speed)
func void Mdl_SetNpcSpeedMultiplier( var C_Npc npc, var float multiplier ) {};\n
npc
- npc to be affected multiplier
- speed of the animation "},{"location":"zengin/scripts/extenders/zparserextender/externals/mdl/#mdl_resetnpcspeedmultiplier","title":"Mdl_ResetNpcSpeedMultiplier
","text":"Mdl_ResetNpcSpeedMultiplier
Resets the animation speed of an NPC
func void Mdl_ResetNpcSpeedMultiplier( var C_Npc npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/","title":"Menu function","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#menu-function","title":"Menu function","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#menu_searchitems","title":"Menu_SearchItems
","text":"Menu_SearchItems
Find all C_MenuItem object instances by the mask and automatically places them in the current menu instance
func void Menu_SearchItems( var string mask ) {};\n
mask
- regex like mask for searching "},{"location":"zengin/scripts/extenders/zparserextender/externals/menu/#example","title":"Example","text":"This function is used in the Union Menu API script. In this script the Menu_SearchItems
external is used to collect all Union menu scripts that are placed into the Union & Plugins menu that will appear in the game if you use any of the plugins that use this feature.
Usage of Menu_SearchItems external functioninstance MENU_OPT_UNION(C_MENU_DEF)\n{\n Menu_SearchItems(\"MENUITEM_UNION_AUTO_*\");\n MENU_OPT_UNION_PY = 1200;\n backpic = MENU_BACK_PIC;\n items[0] = \"UNION_MENUITEM_TITLE\";\n items[100] = \"UNION_MENUITEM_BACK\";\n defaultoutgame = 0;\n defaultingame = 0;\n Flags = Flags | MENU_SHOW_INFO;\n};\n
In this case all instances are of the name MENUITEM_UNION_AUTO_*
where *
is a wildcard that can be substituted with anything. The plugin will search the scripts and find all instances (in the case of zGamePad it is MenuItem_Union_Auto_zGamePad
)
This example comes from the zUnionMenu.d
injectable API script that is part of the zGamePad plugin, GitHub link.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/","title":"MOB - interactive object functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob---interactive-object-functions","title":"MOB - interactive object functions","text":"Functions to manipulate interactive objects like destroying MOBs, setting lockpick combination and such.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_destroy","title":"Mob_Destroy
","text":"Mob_Destroy
Marks oCMOB as destroyed, changes the visual to visualDestroyed (if present).
func void Mob_Destroy( var instance object ) {};\n
object
- oCMOB to be destroyed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_removeitem","title":"Mob_RemoveItem
","text":"Mob_RemoveItem
Removes an item from a oCMobContainer
func void Mob_RemoveItem( var instance object, var int item ) {};\n
object
- oCMobContainer object item
- item to be removed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_removeitems","title":"Mob_RemoveItems
","text":"Mob_RemoveItems
Removes specified number of items from a oCMobContainer
func void Mob_RemoveItems( var instance object, var int item, var int cnt ) {};\n
object
- oCMobContainer object item
- item to be removed cnt
- number of items to be removed "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_insertitem","title":"Mob_InsertItem
","text":"Mob_InsertItem
Inserts an item into a oCMobContainer
func void Mob_InsertItem( var instance object, var int item ) {};\n
object
- oCMobContainer object item
- item to be inserted "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_insertitems","title":"Mob_InsertItems
","text":"Mob_InsertItems
Inserts specified number of items into a oCMobContainer
func void Mob_InsertItems( var instance object, var int item, var int cnt ) {};\n
object
- oCMobContainer object item
- item to be inserted cnt
- number of items to be inserted "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_getlockcombination","title":"Mob_GetLockCombination
","text":"Mob_GetLockCombination
Returns a lock combination of a oCMobContainer
func string Mob_GetLockCombination( var instance object ) {};\n
object
- oCMobContainer object return
- lock combination "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setlockcombination","title":"Mob_SetLockCombination
","text":"Mob_SetLockCombination
Sets a lock combination to a oCMobContainer
func void Mob_SetLockCombination( var instance object, var string comb ) {};\n
object
- oCMobContainer object comb
- lock combination "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_islocked","title":"Mob_IsLocked
","text":"Mob_IsLocked
Returns TRUE
if the object is locked
func int Mob_IsLocked( var instance object ) {};\n
object
- oCMobLockable object return
- TRUE
if locked, FALSE
if unlocked "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setlocked","title":"Mob_SetLocked
","text":"Mob_SetLocked
Set the lock status of the object
func void Mob_SetLocked( var instance object, var int locked ) {};\n
object
- oCMobLockable object locked
- lock or unlock the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_getkeyinstance","title":"Mob_GetKeyInstance
","text":"Mob_GetKeyInstance
Returns the key instance, that unlocks the object
func instance Mob_GetKeyInstance( var instance object ) {};\n
object
- oCMobLockable object return
- the key C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/mob/#mob_setkeyinstance","title":"Mob_SetKeyInstance
","text":"Mob_SetKeyInstance
Stets the key instance, that unlocks the object
func void Mob_SetKeyInstance( var instance object, var int key ) {};\n
object
- oCMobLockable object key
- the key C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/","title":"NPC - character functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc---character-functions","title":"NPC - character functions","text":"NPC related functions.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_setashero","title":"Npc_SetAsHero
","text":"Npc_SetAsHero
Changes players character to specified npc
func void Npc_SetAsHero( var C_NPC npc ) {};\n
npc
- NPC to be set as players character "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventory","title":"Npc_OpenInventory
","text":"Npc_OpenInventory
Opens NPCs main inventory
func void Npc_OpenInventory( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventorysteal","title":"Npc_OpenInventorySteal
","text":"Npc_OpenInventorySteal
Opens the steal inventory of npc
's focus NPC
func void Npc_OpenInventorySteal( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_openinventorytrade","title":"Npc_OpenInventoryTrade
","text":"Npc_OpenInventoryTrade
Start the trading dialogue with specified NPC
func void Npc_OpenInventoryTrade( var C_NPC npc ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getlefthanditem","title":"Npc_GetLeftHandItem
","text":"Npc_GetLeftHandItem
Returns an item in NPC's left hand slot
func C_Item Npc_GetLeftHandItem( var C_Npc npc ) {};\n
npc
- npc to be affected return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getrighthanditem","title":"Npc_GetRightHandItem
","text":"Npc_GetRightHandItem
Returns an item in NPC's right hand slot
func C_Item Npc_GetRightHandItem( var C_Npc npc ) {};\n
npc
- npc to be affected return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_getslotitem","title":"Npc_GetSlotItem
","text":"Npc_GetSlotItem
Returns an item from a slot with the slotName
func C_Item Npc_GetSlotItem( var C_Npc npc, var string slotName ) {};\n
npc
- npc to be affected slotName
- name of the slot return
- found C_ITEM instance "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_putinslot","title":"Npc_PutInSlot
","text":"Npc_PutInSlot
Places an instance of the oCVom class (including items and NPCs) object into the slotName of the NPC The copyInInv parameter determines whether a copy of the object should remain in the character's inventory
func void Npc_PutInSlot(var C_Npc npc, var string slotName, var instance object, var int copyInInv) {};\n
npc
- npc to remove the item from slotName
- name of the slot from which to remove the item object
- object to be inserted into the slot copyInInv
- should a copy of the object stay in character inventory "},{"location":"zengin/scripts/extenders/zparserextender/externals/npc/#npc_removefromslot","title":"Npc_RemoveFromSlot
","text":"Npc_RemoveFromSlot
Removes an object from the slotName of the NPC. The dropIt parameter in Gothic 2 defines, whether object should drop out of the slot. In Gothic 1, this parameter is reserved and must be 0.
func void Npc_RemoveFromSlot(var C_Npc npc, var string slotName, var int dropIt) {};\n
npc
- npc to remove the item from slotName
- name of the slot from which to remove the item dropIt
- should the object be dropped "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/","title":"PAR - functions for parser manipulation","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par---functions-for-parser-manipulation","title":"PAR - functions for parser manipulation","text":"Parser functions are used to manipulate the parsers. Retrieve SymbolID, access arrays and such.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getparserid","title":"Par_GetParserID
","text":"Par_GetParserID
Returns a parser ID of the parser with a parName
name
Parser names:
\"Game\"
\"SFX\"
\"PFX\"
\"VFX\"
\"Camera\"
\"Menu\"
\"Music\"
func int Par_GetParserID(var string parName) {};\n
parName
- parser name return
- parser ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolid","title":"Par_GetSymbolID
","text":"Par_GetSymbolID
Returns symbol ID for the symbol specified by its name
func int Par_GetSymbolID(var int parId, var string symName) {};\n
parID
- parser ID symName
- symbol name return
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbollength","title":"Par_GetSymbolLength
","text":"Par_GetSymbolLength
Returns symbol length (number of elements)
func int Par_GetSymbolLength(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol length "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueint","title":"Par_GetSymbolValueInt
","text":"Par_GetSymbolValueInt
Returns the integer value of specified symbol
func int Par_GetSymbolValueInt(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluefloat","title":"Par_GetSymbolValueFloat
","text":"Par_GetSymbolValueFloat
Returns the float value of specified symbol
func float Par_GetSymbolValueFloat(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluestring","title":"Par_GetSymbolValueString
","text":"Par_GetSymbolValueString
Returns the string value of specified symbol
func string Par_GetSymbolValueString(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueinstance","title":"Par_GetSymbolValueInstance
","text":"Par_GetSymbolValueInstance
Returns the instance value of specified symbol
func instance Par_GetSymbolValueInstance(var int parId, var int symId) {};\n
parID
- parser ID symName
- symbol name return
- symbol value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvalueintarray","title":"Par_GetSymbolValueIntArray
","text":"Par_GetSymbolValueIntArray
Returns the value of specified integer array at the arrayID
index
func int Par_GetSymbolValueIntArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluefloatarray","title":"Par_GetSymbolValueFloatArray
","text":"Par_GetSymbolValueFloatArray
Returns the value of specified float array at the arrayID
index
func float Par_GetSymbolValueFloatArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_getsymbolvaluestringarray","title":"Par_GetSymbolValueStringArray
","text":"Par_GetSymbolValueStringArray
Returns the value of specified string array at the arrayID
index
func string Par_GetSymbolValueStringArray(var int parId, var int symId, var int arrayId) {};\n
parID
- parser ID symName
- symbol name arrayID
- array index return
- value "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueint","title":"Par_SetSymbolValueInt
","text":"Par_SetSymbolValueInt
Sets a new integer value to specified symbol
func void Par_SetSymbolValueInt(var int value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluefloat","title":"Par_SetSymbolValueFloat
","text":"Par_SetSymbolValueFloat
Sets a new float value to specified symbol
func void Par_SetSymbolValueFloat(var float value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluestring","title":"Par_SetSymbolValueString
","text":"Par_SetSymbolValueString
Sets a new string value to specified symbol
func void Par_SetSymbolValueString(var string value, var int parId, var int symId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueinstance","title":"Par_SetSymbolValueInstance
","text":"Par_SetSymbolValueInstance
Sets a new instance value to specified symbol
func void Par_SetSymbolValueInstance(var instance value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvalueintarray","title":"Par_SetSymbolValueIntArray
","text":"Par_SetSymbolValueIntArray
Sets a new integer value to specified integer array symbol
func void Par_SetSymbolValueIntArray(var int value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluefloatarray","title":"Par_SetSymbolValueFloatArray
","text":"Par_SetSymbolValueFloatArray
Sets a new float value to specified float array symbol
func void Par_SetSymbolValueFloatArray(var float value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/par/#par_setsymbolvaluestringarray","title":"Par_SetSymbolValueStringArray
","text":"Par_SetSymbolValueStringArray
Sets a new string value to specified string array symbol
func void Par_SetSymbolValueStringArray(var string value, var int parId, var int symId, var int arrayId) {};\n
value
- value to be set parID
- parser ID symId
- symbol ID arrayId
- array index "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/","title":"String functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#string-functions","title":"String functions","text":"Functions to manipulate and format strings.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_format","title":"Str_Format
","text":"Str_Format
Returns formatted string using format specifiers
Format specifiers:
%s
- inserts a string %i
- inserts an integer number %x
- inserts an integer in hexadecimal %f
- inserts a floating point number %b
- inserts a logical expression %p
- inserts a pointer func string Str_Format( var string format, ... ) {};\n
return
- formatted string "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#examples","title":"Examples
","text":"Examples
Very powerful function, can be used to streamline strings used in the scripts as well as optimize them for translations.
Define constants containing the string with format specifiers.
const string MENU_SAVE = \"Slot %i - press ENTER to save in this slot.\";\nconst string MENU_LOAD = \"Slot %i - press ENTER to load saved game.\";\n
Then define two format functions as such:
func string GetSaveSlotString (var int number)\n{\n return Str_format(MENU_SAVE, number);\n};\n
func string GetLoadSlotString (var int number)\n{\n return Str_format(MENU_LOAD, number);\n};\n
Tip
Since the whole translatable string is saved in one constant, it is very easy for translators to change the word order. This was not possible to do without code change to the ConcatStrings
function calls within the scripts. With this simple change, translators have to translate only 2 strings instead of 30 (15 + 15 slots) and only 2 strings are compiled into the compiled Menu.dat
file.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlocalizedstring","title":"Str_GetLocalizedString
","text":"Str_GetLocalizedString
Returns a string in the current language, otherwise in English. Arguments MUST be encoded in UTF-8! The result string will be converted to appropriate ANSI string.
func string Str_GetLocalizedString( var string russian,\n var string english,\n var string german,\n var string polish ) {};\n
russian
- Russian string english
- English string german
- German string polish
- Polish string return
- string in the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlocalizedstringex","title":"Str_GetLocalizedStringEx
","text":"Str_GetLocalizedStringEx
Returns a string in the current language, otherwise in English. Offers additional languages
func string Str_GetLocalizedStringEx( var string russian,\n var string english,\n var string german,\n var string polish,\n var string romanian,\n var string italian,\n var string czech,\n var string spanish ) {};\n
russian
- Russian string english
- English string german
- German string polish
- Polish string romanian
- Romanian string italian
- Italian string czech
- Czech string spanish
- Spanish string return
- string in the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_utf8_to_ansi","title":"Str_UTF8_to_ANSI
","text":"Str_UTF8_to_ANSI
Converts UTF-8 string into an ANSI string with codePage
func string Str_UTF8_to_ANSI( var string utf8, var int codePage ) {};\n
utf8
- string encoded in UTF8 codePage
- codePage id, can be obtained from Str_GetCurrentCP return
- "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getcurrentcp","title":"Str_GetCurrentCP
","text":"Str_GetCurrentCP
Return the code page corresponding to the current language set in the Union System
func int Str_GetCurrentCP() {};\n
return
- code page corresponding to the current language "},{"location":"zengin/scripts/extenders/zparserextender/externals/string/#str_getlength","title":"Str_GetLength
","text":"Str_GetLength
Returns the length of a string
func int Str_GetLength( var int str ) {};\n
str
- string to be measured return
- length of the string "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/","title":"VOB - functions for object manipulation","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob---functions-for-object-manipulation","title":"VOB - functions for object manipulation","text":"VOB functions allow you to manipulate game world objects.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getvobposition","title":"Vob_GetVobPosition
","text":"Vob_GetVobPosition
Returns the current position of the object in the world
func C_Position Vob_GetVobPosition( var C_Vob vob ) {};\n
vob
- vob to ge the position of return
- C_Position instance - position of the VOB "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setvobposition","title":"Vob_SetVobPosition
","text":"Vob_SetVobPosition
Sets the current position of the object in the world
func void Vob_SetVobPosition( var C_Vob vob, var C_Position pos ) {};\n
vob
- vob to get the position of pos
- new position of the vob "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getvobdata","title":"Vob_GetVobData
","text":"Vob_GetVobData
Returns the universal data of the zCVob object
func C_Vob_Data Vob_GetVobData( var C_Vob vob ) {};\n
vob
- VOB to get the position of return
- general vob data C_Vob_Data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setvobdata","title":"Vob_SetVobData
","text":"Vob_SetVobData
Sets the universal data to a zCVob object
func void Vob_SetVobData( var C_Vob vob, var C_Vob_Data data ) {};\n
vob
- VOB to get the position of data
- general vob data C_Vob_Data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getlightdata","title":"Vob_GetLightData
","text":"Vob_GetLightData
Returns zCVobLight object data
func C_Light_Data Vob_GetLightData( var C_Vob vobLight ) {};\n
vobLight
- vobLight object return
- C_Light_Data of the light "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setlightdata","title":"Vob_SetLightData
","text":"Vob_SetLightData
Sets the data of a zCVobLight object
func void Vob_SetLightData( var C_Vob vobLight, var C_Light_Data data ) {};\n
vobLight
- object to apply the light data to data
- C_Light_Data light data to be set "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_clearlightanilist","title":"Vob_ClearLightAniList
","text":"Vob_ClearLightAniList
Clears the list of animation colours for the light source
func void Vob_ClearLightAniList( var C_Vob vobLight ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_addlightanicolor","title":"Vob_AddLightAniColor
","text":"Vob_AddLightAniColor
Adds a color to the colour list
func void Vob_AddLightAniColor( var C_Vob vobLight, var C_Color col ) {};\n
vobLight
- object to apply the colour to col
- colour to be applied "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_addlightanicolorrgb","title":"Vob_AddLightAniColorRGB
","text":"Vob_AddLightAniColorRGB
Adds a color to the colour list
func void Vob_AddLightAniColorRGB( var C_Vob vobLight,\n var int r,\n var int g,\n var int b ) {};\n
vobLight
- object to apply the colour to r
- red colour channel g
- green colour channel b
- blue colour channel "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobdata","title":"Vob_GetMobData
","text":"Vob_GetMobData
Returns the data of the oCMOB object
func C_Mob_Data Vob_GetMobData( var C_Vob mob ) {};\n
mob
- oCMOB object return
- mob data "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobdata","title":"Vob_SetMobData
","text":"Vob_SetMobData
Sets the data of the oCMOB object
func void Vob_SetMobData( var C_Vob mob, var C_Mob_Data data ) {};\n
mob
- oCMOB object data
- C_Mob_Data to be set "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobinterdata","title":"Vob_GetMobInterData
","text":"Vob_GetMobInterData
Returns the data of the oCMobInter object
func MobInter_Data Vob_GetMobInterData( var C_Vob mobInter ) {};\n
mobInter
- oCMobInter object return
- MobInter_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobinterdata","title":"Vob_SetMobInterData
","text":"Vob_SetMobInterData
Sets the data of the oCMobInter object
func void Vob_SetMobInterData( var C_Vob mobInter, var C_MobInter_Data data ) {};\n
mobInter
- oCMobInter object data
- MobInter_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_getmobinterdata_1","title":"Vob_GetMobInterData
","text":"Vob_GetMobInterData
Returns the data of the oCMobLockable object
func C_MobLockable_Data Vob_GetMobInterData( var C_Vob mobLock ) {};\n
mobLock
- oCMobLockable object data
- MobInter_Data of the object return
- C_MobLockable_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/vob/#vob_setmobinterdata_1","title":"Vob_SetMobInterData
","text":"Vob_SetMobInterData
Sets the data of the oCMobLockable object
func void Vob_SetMobInterData( var C_Vob mobLock, var C_MobLockable_Data data ) {};\n
mobLock
- oCMobLockable object data
- C_MobLockable_Data of the object "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/","title":"WLD - world manipulation functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld---world-manipulation-functions","title":"WLD - world manipulation functions","text":"Functions related to the world.
"},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_changelevel","title":"Wld_ChangeLevel
","text":"Wld_ChangeLevel
Trigger level change.
func void Wld_ChangeLevel( var string world, var string waypoint ) {};\n
world
- name of the world waypoint
- target waypoint "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_findvob","title":"Wld_FindVob
","text":"Wld_FindVob
Return the VOB instance based on its name.
func instance Wld_FindVob( var string vobname ) {};\n
vobname
- name of the vob return
- zCVob pointer "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_playeffectvob","title":"Wld_PlayEffectVob
","text":"Wld_PlayEffectVob
Play a visual effect at specified vob
func void Wld_PlayEffectVob( var string effect,\n var instance pvob,\n var int level,\n var int damage,\n var int damage_type,\n var int damage_speed ) {};\n
effect
- effect name pvob
- zCVob to play the effect at level
- effect level damage
- damage amount damage_type
- damage type damage_speed
- damage interval "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_playeffectat","title":"Wld_PlayEffectAt
","text":"Wld_PlayEffectAt
Play a visual effect at specified world coordinates
func void Wld_PlayEffectAt( var string effect,\n var instance coord,\n var int level,\n var int damage,\n var int damage_type,\n var int damage_speed ) {};\n
effect
- effect name coord
- world coordinates (zVEC3
) to play the effect at level
- effect level damage
- damage amount damage_type
- damage type damage_speed
- damage interval "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_togglerain","title":"Wld_ToggleRain
","text":"Wld_ToggleRain
Turns on the rain
func void Wld_ToggleRain( var float weight, var float time ) {};\n
weight
- the strength of the rain time
- rain duration "},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_setweathertype","title":"Wld_SetWeatherType
","text":"Wld_SetWeatherType
Sets the weather type. Types:
0
- snow 1
- rain
func void Wld_SetWeatherType( var int type ) {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/externals/wld/#wld_getweathertype","title":"Wld_GetWeatherType
","text":"Wld_GetWeatherType
Returns the weather type. Types:
0
- snow 1
- rain
func int Wld_GetWeatherType() {};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/","title":"Dialogue constants","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dialogue-constants","title":"Dialogue constants","text":"To simplify dialogues, you can define up to 2 auxiliary variables or constants. Values corresponding to the current C_Info
instance will be dynamically written there.
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dia_currentinstance","title":"DIA_CurrentInstance","text":"var int DIA_CurrentInstance\n
Contains the ID of the current C_Info
instance. Can greatly simplify code or make it more reusable. Should be defined in scripts. Example usageInfo_ClearChoices(DIA_CurrentInstance);\nInfo_AddChoice(DIA_CurrentInstance, /*text*/, /*func*/);\nNpc_KnowsInfo(hero, DIA_CurrentInstance); // In this case DIA_CurrentInstance contains the last C_Info instance??\n
Create a wrapper function based on this variablefunc int C_HeroKnowsCurrentInfo()\n{\n return Npc_KnowsInfo(hero, DIA_CurrentInstance);\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/#dia_currentname","title":"DIA_CurrentName","text":"var string DIA_CurrentName;\n
Contains the name of the current instance of C_Info
. Can be useful for debugging purposes. Should be defined in scripts. Usage scenarios: Hlp_PrintConsole(DIA_CurrentName);\nHlp_PrintConsole(Str_Format(\"%s[%s]\", DIA_CurrentName, self.name);\nHlp_StrCmp(DIA_CurrentName, \"DIA_DiegoOw_Teach\");\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/events/","title":"Event functions","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/events/#event-functions","title":"Event functions","text":"Event functions are functions sharing the same name. It can be defined multiple times but only once per file. Such functions are useful for implementing callback type functions. Every time an event is called, all instances of the same name will be called. The event is func
with a return type event
. Events are defined globally, meaning they ignore namespace they are in. To call an event from a script, use the external function Hlp_DoEvent(var string funcName)
.
func void GiveXP()\n{\n Hlp_DoEvent(\"OnGiveXP\");\n};\n\nfunc event OnGiveXP()\n{\n // TODO\n // This function can be defined in many files to do different things\n // more appropriate for that file's context and all of them will be\n // called, when function GiveXP (above) is called.\n};\n
Plugin implements two of these event functions
func event GameInit()
- called when entering the main menu on game start func event GameLoop()
- called every frame when a world is loaded Define these in any file in your scripts, they will be automatically called
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/extern/","title":"Extern binding","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/extern/#extern-binding","title":"Extern binding","text":"The extern
binding allows you to secure your code against overriding or undefined symbol. Keyword extern
before declaration means that if object of the same name exists, source object should be used. If not, a new one will be created.
extern instance PC_Hero(C_Npc) \n{\n // TODO\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/","title":"Namespaces","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespaces","title":"Namespaces","text":"zParserExtender also implements namespaces. Namespaces ensure that all symbols inside the namespace are unique.
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#defining-a-namespace","title":"Defining a namespace","text":"To define a namespace the new keyword namespace
is used.
Regular scriptsInjectable scripts namespace zTestNamespace\n{\n var int var01;\n func void func01() { };\n};\n
META\n{\n Namespace = zTestNamespace;\n};\n\nvar int var01;\nfunc void func01() { };\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespace-nesting","title":"Namespace nesting","text":"Namespaces can be nested for finer control. In case of injection, the namespace defined in META is applied to all code inside the script.
To go deeper into the namespaces you use the namespace operator :
. This code shows function with the same name within three different namespaces. The call in GameInit
is made from the global namespace.
namespace zTestNamespace01\n{\n func void func01() { };\n};\n\nnamespace zTestNamespace02\n{\n func void func01() { };\n};\n\nnamespace zTestNamespace03\n{\n namespace zTestNamespace04\n {\n func void func01() { };\n };\n};\n\nfunc event GameInit()\n{\n // In this case, the reference is from global namespace to zTestNamespace\n zTestNamespace01:func01();\n zTestNamespace02:func01();\n zTestNamespace03:zTestNamespace04:func01();\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#namespace-traversal","title":"Namespace traversal","text":"To go up a namespace tree you use the namespace operator :
without specifying a namespace. Number of operators determines how many levels you go up.
Exiting nested namespacesfunc void func01()\n{\n Hlp_MessageBox(\"#1\");\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#2\");\n };\n\n namespace zTestNamespace02\n {\n func void func01()\n {\n Hlp_MessageBox(\"#3\");\n };\n\n namespace zTestNamespace03\n {\n func void func01()\n {\n Hlp_MessageBox(\"#4\");\n };\n\n func event GameInit()\n {\n :::func01(); // Calls the function 3 levels up\n ::func01(); // Calls the function 2 levels up\n :func01(); // Calls the function 1 level up\n func01(); // Calls the function from the current namespace\n };\n };\n };\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#optional-namespace-specification","title":"Optional namespace specification","text":"There are three cases where the namespace prefix is optional
Shares the same namespaceIf the function is in higher level namespaceIf using
is specified in the META block namespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#1\");\n };\n\n func event GameInit()\n {\n // Function call from the current namespace\n func01();\n };\n};\n
func void func01()\n{\n Hlp_MessageBox(\"#1\");\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#2\");\n };\n\n namespace zTestNamespace02\n {\n func event GameInit()\n {\n // Function call from the global namespace\n func01();\n };\n };\n};\n
META\n{\n using = zTestNamespace01;\n};\n\nnamespace zTestNamespace01\n{\n func void func01()\n {\n Hlp_MessageBox(\"#1\");\n };\n};\n\nfunc event GameInit()\n{\n // Calls the function with the namespace specified in the META block\n func01();\n};\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/#global-namespace-and-daedalus-hooking","title":"Global namespace and Daedalus hooking","text":"Namespace can not only be defined to an existing symbol but also to define new ones. Next code example shows how to implement a hook to a global instance.
namespace zTestNamespace01\n{\n const string Var01 = \"New instance name\";\n\n // Hooking the global instance\n instance :ItAr_Pir_L_Addon(C_Item)\n {\n ItAr_Pir_L_Addon_Old();\n name = Var01;\n };\n};\n
To hook an object, both signature and namespace has to match. It is syntactically allowed to hook an instance from a different space. Specify explicitly to which namespace the object will belong. This means that to hook instance ItAr_Pir_L_Addon
from the namespace zTestNamespace01
to a global namespace, you have to refer to the global namespace using the namespace operator :
. Since the function will be defined globally (as every symbol in ZenGin), it will be a part of the zTestNamespace01
which means that all functions will be local to this namespace."},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/","title":"Test-else statements","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/#test-else-statements","title":"Test-else statements","text":"The test-else bind statement can be used to define sections of code to be compiled. If the code is within the boundaries of the inactive test-else branch, it will not be compiled. This operator can take values as input that are converted to logical values. For example, if an object is passed as an argument, the parser will check for its existence. If it is an engine tag, it will return the result of matching the current engine with the tag:
Valid values:
instance name - PC_HERO
, ItMi_Gold
, ... engine tag - G1
, G1A
, G2
, G2A
Steam Overlay activity - Steam
The result can be combined from several arguments. Round brackets ()
can be used to specify priority and expressions support the logical negation operator !
, logical AND &&
and OR ||
.
The operator can be used anywhere in the script file. It is syntactically similar to if else
statement, but curly braces {}
can be omitted for single-line operations. For example:
SteamActivated constant is set only when Steam is activetest Steam var const SteamActivated = 1;\n
Example of a logical expression with an else branchtest SteamActivated && G2A \n{\n // TODO\n}\nelse \n{\n // TODO\n}\n
"},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/while/","title":"Native WHILE loop","text":""},{"location":"zengin/scripts/extenders/zparserextender/syntax_extensions/while/#native-while-loop","title":"Native WHILE loop","text":"Just like Ikarus zParserExtender implements a while loop.
var int value; value = 10;\nwhile(value > 0)\n{\n if (value == 8)\n {\n continue;\n };\n\n if (value == 2)\n {\n break;\n };\n};\n
Note
To activate while
it is necessary to set NativeWhile
setting in SystemPack.ini
[ZPARSE_EXTENDER]\nNativeWhile = true\n
Compiled while loop works in vanilla engine without the plugin.
"},{"location":"zengin/scripts/externals/","title":"Externals","text":""},{"location":"zengin/scripts/externals/#externals","title":"Externals","text":"External functions are Daedalus functions (defined in the engine itself), that are used to interface with the engine. Gothic 1 and Gothic 2 implements slightly different set of external functions. There are some external functions, that were used in the course of Gothic's development, but are now obsolete/deprecated because the underlying systems implemented in the engine were either turned off, or broken all together.
"},{"location":"zengin/scripts/externals/doc/","title":"Doc external functions","text":""},{"location":"zengin/scripts/externals/doc/#doc-external-functions","title":"Doc external functions","text":"Doc functions are used to control the document manager. They allow you to fine tune the display of maps, letters and books.
"},{"location":"zengin/scripts/externals/doc/#doc_create","title":"Doc_Create
","text":"Doc_Create
Creates a new instance of the document manager and returns its ID.
func int Doc_Create() {};\n
Return value Returns the ID of the document manager instance.
Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_Create();\n
"},{"location":"zengin/scripts/externals/doc/#doc_createmap","title":"Doc_CreateMap
","text":"Doc_CreateMap
Creates a new instance of the document manager with the arrow showing players position on the map and returns its ID.
func int Doc_CreateMap() {};\n
Return value Returns the ID of the document manager instance.
Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_CreateMap();\n
"},{"location":"zengin/scripts/externals/doc/#doc_setlevel","title":"Doc_SetLevel
","text":"Doc_SetLevel
Set a world level to a map. This maps the texture of the document to the bounding box of the provided level.
func void Doc_SetLevel(var int docID, var string level) {};\n
Parameters
var int docID
- document manager ID var string level
- name of the ZEN file Example
nDocID = Doc_CreateMap();\nDoc_SetLevel(nDocID, \"WORLD.ZEN\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_setlevelcoords","title":"Doc_SetLevelCoords
","text":"Doc_SetLevelCoords
Warning
This function is only available in Gothic 2
Sets the map coordinates. This is used to map smaller portions of the world map to the document map to correctly show players position on the map.
func void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {};\n
Parameters
var int docID
- document manager ID var int left
- left coordinate var int top
- top coordinate var int right
- right coordinate var int bottom
- bottom coordinate Example
Doc_SetLevelCoords(nDocID, -28000, 50500, 95500, -42500);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setfont","title":"Doc_SetFont
","text":"Doc_SetFont
Sets a font
to be used on a page
in a document with docID
. Can be called multiple times to display different lines with different fonts.
func void Doc_SetFont(var int docID, var int page, var string font) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, fonts will be applied to all pages var string font
- font to be used Example
Doc_SetFont(nDocID, -1, \"FONT_10_BOOK.TGA\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_setpages","title":"Doc_SetPages
","text":"Doc_SetPages
Sets the number of pages numOfPages
of the document.
func void Doc_SetPages(var int docID, var int numOfPages) {};\n
Parameters
var int docID
- document manager ID var int numOfPages
- number of pages Example
nDocID = Doc_Create();\nDoc_SetPages(nDocID, 2);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setpage","title":"Doc_SetPage
","text":"Doc_SetPage
Set page
to have texture
as a background with scale
.
func void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, settings are applied to all pages var string texture
- texture of the background var int scale
- scale of the texture, TRUE
to scale the page, FALSE
to not scale Example
Doc_SetPage(nDocID, 0, \"Book_Mage_L.tga\", FALSE);\nDoc_SetPage(nDocID, 1, \"Book_Mage_R.tga\", FALSE);\n
"},{"location":"zengin/scripts/externals/doc/#doc_setmargins","title":"Doc_SetMargins
","text":"Doc_SetMargins
Sets text margins of the page
func void Doc_SetMargins(var int docID,\n var int page,\n var int left,\n var int top,\n var int right,\n var int bottom,\n var int pixels) {};\n
Parameters
var int docID
- document manager ID var int page
- page index, if set to -1
, settings are applied to all pages var int left
- left margin var int top
- top margin var int right
- right margin var int bottom
- bottom margin var int pixels
- TRUE
to use pixels, FALSE
to use virtual coordinates Warning
After a thorough examination of this external function in the decompiler, it looks like the function works in pixels only regardless of this parameter.
Example
Doc_SetMargins(nDocID, 0, 275, 20, 30, 20, TRUE);\n
"},{"location":"zengin/scripts/externals/doc/#doc_printline","title":"Doc_PrintLine
","text":"Doc_PrintLine
Prints a line of text
(font is set using Doc_SetFont) onto the document with docID
, onto the page
. Does not split the text into multiple lines if they do not fit onto the page.
func void Doc_PrintLine(var int docID, var int page, var string text) {};\n
Parameters
var int docID
- document manager ID var int page
- page index var string text
- text to be printed Example
Doc_PrintLine(nDocID, 0, \"\"); // insert empty line\nDoc_PrintLine(nDocID, 0, \"The Book\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_printlines","title":"Doc_PrintLines
","text":"Doc_PrintLines
Prints a line of text
(font is set using Doc_SetFont) onto the document with docID
, onto the page
. Splits the text into multiple lines if they do not fit onto the page.
func void Doc_PrintLines(var int docID, var int page, var string text) {};\n
Parameters
var int docID
- document manager ID var int page
- page index var string text
- text to be printed Example
Doc_PrintLines(nDocID, 0, \"The war had been decided. Varant had lost its seaports, vital to army supplies. King Rhobar had not lingered on the battle fields for a long time, but left his generals to deal with the few remaining enemy troops. Varant had only one large force left, commanded by Lukkor, the most capable warlord of the Varant army, who had more than once turned defeat into victory.\");\nDoc_PrintLines(nDocID, 0, \"But now his army was trapped. The situation was hopeless, even though his army greatly outnumbered the enemy. Lee, a war hero from Myrtana, had lured him into this trap. The heavy cavalry had been unable to fight on the thick, swamped ground of the narrow valley. Lee's soldiers had occupied the range of hills surrounding the swamp, and they had struck repeatedly, decimating the army. The desperate sallies his troops had launched had been cut short in pools of blood. He was beaten.\");\n
"},{"location":"zengin/scripts/externals/doc/#doc_show","title":"Doc_Show
","text":"Doc_Show
Display the document using the document manager ID
func void Doc_Show(var int docID) {};\n
Parameters
var int docID
- document manager ID Example
var int nDocID; // Variable to store the id in\nnDocID = Doc_Create();\n\n// ... document configuration\n\nDoc_Show(nDocID);\n
"},{"location":"zengin/scripts/externals/doc/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Creates a new instance of the document manager and returns its ID.\n///\n/// @return Returns the ID of the document manager instance.\nfunc int Doc_Create() {};\n\n/// Create a new instance of the document manager with the arrow showing players position on the map and returns its ID.\n///\n/// @return Returns the ID of the document manager instance.\nfunc int Doc_CreateMap() {};\n\n/// Prints a line of `text` onto the document with `docID`, onto the `page`.\n/// Does not line break\n/// \n/// @param docID document manager ID\n/// @param page page index\n/// @param text text to be printed\nfunc void Doc_PrintLine(var int docID, var int page, var string text) {};\n\n/// Prints a line of `text` onto the document with `docID`, onto the `page`. The `text` is automatically split into multiple lines\n/// \n/// @param docID document manager ID\n/// @param page page index\n/// @param text text to be printed\nfunc void Doc_PrintLines(var int docID, var int page, var string text) {};\n\n/// Sets a `font` to be used on a `page` in a document with `docID`. Can be called multiple times to display different lines with different fonts.\n///\n/// @param docID document manager ID\n/// @param page page index\n/// @param font font to be used\nfunc void Doc_SetFont(var int docID, var int page, var string font) {};\n\n/// Sets the number of pages `numOfPages` of the document.\n///\n/// @param docID document manager ID\n/// @param numOfPages number of pages\nfunc void Doc_SetPages(var int docID, var int numOfPages) {};\n\n/// Set `page` to have `texture` as a background with `scale`. \n///\n/// @param docID document manager ID\n/// @param page page index, if set to `-1`, settings are applied to all pages\n/// @param texture texture of the background\n/// @param scale scale of the texture, if set to 1, there will be no resizing\nfunc void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {};\n\n/// Set a world level to a map.\n///\n/// @param docID document manager ID\n/// @param level name of the ZEN file\nfunc void Doc_SetLevel(var int docID, var string level) {};\n\n/// Sets the map coordinates. \n/// \n/// @param docID document manager ID\n/// @param left left\n/// @param top top\n/// @param right top\n/// @param bottom bottom\nfunc void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {};\n\n/// Sets text margins of the page\n///\n/// @param docID document manager ID\n/// @param page page index, if set to `-1`, settings are applied to all pages\n/// @param left left margin\n/// @param top top margin\n/// @param right right margin\n/// @param bottom bottom margin\n/// @param pixels `TRUE` to use pixels, `FALSE` to use virtual coordinates\nfunc void Doc_SetMargins(var int docID,\n var int page,\n var int left,\n var int top,\n var int right,\n var int bottom,\n var int pixels) {};\n\n/// Display the document using the document manager ID\n///\n/// @param docID document manager ID\nfunc void Doc_Show(var int docID) {};\n\n\n\n/// deprecated\nfunc void Doc_Open (var string Texture) {};\n\n/// deprecated\nfunc void Doc_Font(var string Font) {};\n\n/// deprecated\nfunc void Doc_Print (var string Text) {};\n\n/// deprecated\nfunc void Doc_MapCoordinates(var string s0,\n var float r1,\n var float r2,\n var float r3,\n var float r4,\n var float r5,\n var float r6,\n var float r7,\n var float r8) {};\n
"},{"location":"zengin/scripts/externals/log/","title":"Log external functions","text":""},{"location":"zengin/scripts/externals/log/#log-external-functions","title":"Log external functions","text":"Log externals are used to manipulate players log and to track quest progress.
"},{"location":"zengin/scripts/externals/log/#log_createtopic","title":"Log_CreateTopic
","text":"Log_CreateTopic
Creates a new log topic with the name topicName
under the section logSection
func void Log_CreateTopic(var string topicName, var int logSection) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var int logSection
Indicates in which section to create the topic in. Takes constants LOG_MISSION
, LOG_NOTE
as values "},{"location":"zengin/scripts/externals/log/#log_addentry","title":"Log_AddEntry
","text":"Log_AddEntry
Adds an entry to a log topic with the name topicName
under the section logSection
func void Log_AddEntry(var string topicName, var string entry) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var string entry
Content of the new entry Info
In the engine the Log_AddEntry()
is wrapped in a B_LogEntry()
function. This function also handles printing the \"New Journal Entry\" message to the screen and playing the sound effect.
func void B_LogEntry(var string topic, var string entry)\n{\n PrintDebugNpc(PD_ZS_DETAIL, \"B_LogEntry\"); // Logging\n\n Log_AddEntry(topic, entry);\n\n PrintScreen(NAME_NewLogEntry, -1, _YPOS_MESSAGE_LOGENTRY, \"font_old_10_white.tga\", _TIME_MESSAGE_LOGENTRY);\n Snd_Play(\"LogEntry\");\n};\n
"},{"location":"zengin/scripts/externals/log/#log_settopicstatus","title":"Log_SetTopicStatus
","text":"Log_SetTopicStatus
Changes the status of the topic with the name topicName
func void Log_SetTopicStatus(var string topicName, var int status) {};\n
Parameters var string topicName
Unique string used to identify and name the topic var int status
The status to be set. Takes constants LOG_RUNNING
, LOG_SUCCESS
, LOG_FAILED
, LOG_OBSOLETE
as values "},{"location":"zengin/scripts/externals/log/#zparserextender","title":"zParserExtender","text":"The log external function selection is missing functions to retrieve the status of a log entry. There are only functions to read the log status (as discussed on Inside Gothic). As a result of this the original scriptwriters had to define additional variable to track the log status in the scripts, even though the value is being already tracked by the engine. zParserExtender fixes this by introducing new log external functions.
"},{"location":"zengin/scripts/externals/log/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Creates a new log topic with the name `topicName` under the section `logSection`\n/// \n/// @param topicName unique string used to identify and name the topic\n/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in\nfunc void Log_CreateTopic(var string topicName, var int logSection) {};\n\n/// Creates a new log topic with the name `topicName` under the section `logSection`\n/// \n/// @param topicName unique string used to identify and name the topic\n/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in\nfunc void Log_AddEntry(var string topicName, var string entry) {};\n\n/// Changes the status of the topic with the name `topicName`\n///\n/// @param topicName unique string used to identify and name the topic\n/// @param status [LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE] the status to be set\nfunc void Log_SetTopicStatus(var string topicName, var int status) {};\n
"},{"location":"zengin/scripts/externals/mdl/","title":"MDL functions","text":""},{"location":"zengin/scripts/externals/mdl/#mdl-functions","title":"MDL functions","text":"Functions to tweak animation and other model related settings.
"},{"location":"zengin/scripts/externals/mdl/#mdl_applyoverlaymds","title":"Mdl_ApplyOverlayMDS
","text":"Mdl_ApplyOverlayMDS
Apply an animation overlay with overlay_name
for the specified npc
func void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {};\n
Parameters
var c_npc npc
NPC to apply the overlay to var string overlay_name
Name of the animation overlay "},{"location":"zengin/scripts/externals/mdl/#mdl_applyoverlaymdstimed","title":"Mdl_ApplyOverlayMDSTimed
","text":"Mdl_ApplyOverlayMDSTimed
Apply an animation overlay with overlay_name
for the specified npc
for duration
milliseconds
func void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {};\n
Parameters
var c_npc npc
NPC to apply the overlay to var string overlay_name
Name of the animation overlay var float duration
Overlay duration in milliseconds "},{"location":"zengin/scripts/externals/mdl/#mdl_removeoverlaymds","title":"Mdl_RemoveOverlayMDS
","text":"Mdl_RemoveOverlayMDS
Remove the animation overlay overlay_name
from specified npc
func void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {};\n
Parameters
var c_npc npc
NPC to remove the overlay from var string overlay_name
Name of the animation overlay "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomani","title":"Mdl_ApplyRandomAni
","text":"Mdl_ApplyRandomAni
Assign a random animation ani2
to random animation list of animation ani1
func void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {};\n
Parameters
var c_npc npc
NPC owning the animation var string ani1
The animation to assign random animation to var string ani2
Animation to be assigned "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomanifreq","title":"Mdl_ApplyRandomAniFreq
","text":"Mdl_ApplyRandomAniFreq
Sets the random animation frequency for animation ani1
func void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {};\n
Parameters
var c_npc npc
NPC owning the animation var string ani1
The animation to set the random frequency var float frequency
Number of seconds between random animations Example // Attach T_WOUNDED_TRY animation to the S_WOUNDED animation\nMdl_ApplyRandomAni(self, \"S_WOUNDED\", \"T_WOUNDED_TRY\");\n// Make the random animation attached play every 8 seconds\nMdl_ApplyRandomAniFreq(self, \"S_WOUNDED\", 8);\n
"},{"location":"zengin/scripts/externals/mdl/#mdl_setmodelfatness","title":"Mdl_SetModelFatness
","text":"Mdl_SetModelFatness
Set the procedural model fatness
func void Mdl_SetModelFatness(var c_npc npc, var float fatness) {};\n
Parameters
var c_npc npc
NPC to apply the fatness to var float fatness
Fatness value "},{"location":"zengin/scripts/externals/mdl/#mdl_setmodelscale","title":"Mdl_SetModelScale
","text":"Mdl_SetModelScale
Set model scale per axis
func void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {};\n
Parameters
var c_npc npc
NPC to apply the scale to var float x
Scale along the x-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% var float y
Scale along the y-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% var float z
Scale along the z-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% "},{"location":"zengin/scripts/externals/mdl/#mdl_setvisualbody","title":"Mdl_SetVisualBody
","text":"Mdl_SetVisualBody
Sets up the visual of an NPC
func void Mdl_SetVisualBody(var instance npc,\n var string body_mesh,\n var int body_tex,\n var int skin,\n var string head_mesh,\n var int head_tex,\n var int teeth_tex,\n var int armor_inst ) {};\n
Parameters
var instance npc
NPC to be affected var string body_mesh
Mesh to be used as the body e.g. HUN_BODY_NAKED0
var int body_tex
Body texture assigned to this body mesh var int skin
Body texture variant var string head_mesh
Head mesh var int head_tex
Head texture var int teeth_tex
Teeth texture var int armor_inst
Armor (C_ITEM
instance) to be equipped or -1
for no armor "},{"location":"zengin/scripts/externals/mdl/#mdl_setvisual","title":"Mdl_SetVisual
","text":"Mdl_SetVisual
Set the animation set (also dictates models you can set using the Mdl_SetVisualBody
)
func void Mdl_SetVisual(var instance npc, var string animation_set) {};\n
Parameters
var instance npc
NPC to apply the animation set to var string animation_set
Name of the MDS file that contains the animation set "},{"location":"zengin/scripts/externals/mdl/#mdl_startfaceani","title":"Mdl_StartFaceAni
","text":"Mdl_StartFaceAni
Start a face animation
func void Mdl_StartFaceAni(var c_npc npc,\n var string name,\n var float intensity,\n var float holdtime) {};\n
Parameters
var c_npc npc
NPC to apply the animation to var string name
Animation name var float intensity
Intensity of the animation 0.0 to 1.0 var float holdtime
How long should the animation be held for -2
will use the MMS defined value, '-1' will make the hold time infinite "},{"location":"zengin/scripts/externals/mdl/#mdl_applyrandomfaceani","title":"Mdl_ApplyRandomFaceAni
","text":"Mdl_ApplyRandomFaceAni
Start a random face animation
func void Mdl_ApplyRandomFaceAni(var c_npc npc,\n var string name,\n var float timemin,\n var float timeminvar,\n var float timemax,\n var float timemaxvar,\n var float probmin) {};\n
Parameters
var c_npc npc
NPC to apply the animation to var string name
Animation name var float timemin
Minimum time after which the ani should be started (in seconds) var float timeminvar
Minimum boundary variation (in seconds) var float timemax
Maximum time after which the ani should be started (in seconds) var float timemaxvar
Maximum boundary variation (in seconds) var float probmin
Probability (0.0 to 1.0) to choose the lower boundary time "},{"location":"zengin/scripts/externals/mdl/#externals-with-docu-comments","title":"Externals with docu comments","text":"/// Apply an animation overlay with `overlay_name` for the specified `npc`\n/// \n/// @param npc NPC to apply the overlay to\n/// @param overlay_name name of the animation overlay\nfunc void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {};\n\n/// Apply an animation overlay with `overlay_name` for the specified `npc` for `duration` milliseconds\n///\n/// @param npc NPC to apply the overlay to\n/// @param overlay_name name of the animation overlay\n/// @param duration overlay duration in milliseconds\nfunc void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {};\n\n/// Remove the animation overlay `overlay_name` from specified `npc` \n/// \n/// @param npc NPC to remove the overlay from\n/// @param overlay_name name of the animation overlay\nfunc void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {};\n\n/// Assign a random animation `ani2` to random animation list of animation `ani1`\n///\n/// @param npc NPC owning the animation\n/// @param ani1 the animation to assign random animation to\n/// @param ani2 animation to be assigned\nfunc void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {};\n\n/// Sets the random animation frequency for animation `ani1`\n///\n/// @param npc NPC owning the animation\n/// @param ani1 the animation to set the random frequency\n/// @param frequency number of seconds between random animations\nfunc void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {};\n\n/// Set the procedural model fatness\n///\n/// @param npc NPC to apply the fatness to \n/// @param fatness fatness value\nfunc void Mdl_SetModelFatness(var c_npc npc, var float fatness) {};\n\n/// Set model scale per axis\n///\n/// @param npc NPC to apply the scale to \n/// @param x scale along the x axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \n/// @param y scale along the y axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \n/// @param z scale along the z axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% \nfunc void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {};\n\n/// Sets up the visual of an NPC\n///\n/// @param npc NPC to be affected\n/// @param body_mesh mesh to be used as the body e.g. `HUN_BODY_NAKED0`\n/// @param body_tex body texture assigned to this body mesh\n/// @param skin body texture variant\n/// @param head_mesh head mesh\n/// @param head_tex head texture\n/// @param teeth_tex teeth texture\n/// @param armor_inst armor (C_ITEM instance) to be equipped or `-1` for no armor \nfunc void Mdl_SetVisualBody(var instance npc,\n var string body_mesh,\n var int body_tex,\n var int skin,\n var string head_mesh,\n var int head_tex,\n var int teeth_tex,\n var int armor_inst ) {};\n\n/// Set the animation set (also dictates models you can set using the `Mdl_SetVisualBody`)\n///\n/// @param npc NPC to apply the animation set to \n/// @param animation_set name of the MDS file that contains the animation set\nfunc void Mdl_SetVisual(var instance npc, var string animation_set) {};\n\n/// Start a face animation\n///\n/// @param npc NPC to apply the animation to \n/// @param name animation name\n/// @param intensity intensity of the animation 0.0 to 1.0\n/// @param holdtime how long should the animation be held for `-2` will use the MMS defined value, '-1' will make the hold time infinite\nfunc void Mdl_StartFaceAni(var c_npc npc,\n var string name,\n var float intensity,\n var float holdtime) {};\n\n/// Start a random face animation\n///\n/// @param npc NPC to apply the animation to \n/// @param name animation name\n/// @param timemin minimum time after which the ani should be started (in seconds)\n/// @param timeminvar minimum boundary variation (in seconds)\n/// @param timemax maximum time after which the ani should be started (in seconds)\n/// @param timemaxvar maximum boundary variation (in seconds)\n/// @param probmin probability (0.0 to 1.0) to choose the lower boundary time\nfunc void Mdl_ApplyRandomFaceAni(var c_npc npc,\n var string name,\n var float timemin,\n var float timeminvar,\n var float timemax,\n var float timemaxvar,\n var float probmin) {};\n
"},{"location":"zengin/sound/","title":"Sound","text":""},{"location":"zengin/sound/#sound","title":"Sound","text":"ZenGin uses .wav
files for playing Sound Effects and Dubbing.
Info
In-game soundtrack isn't saved in .wav
sound files. See Music.
"},{"location":"zengin/sound/#properties","title":"Properties","text":"Original gothic sound files has following properties:
One channel (Mono) 44100 Hz frequency 32-bit depth "},{"location":"zengin/sound/#sfx","title":"SFX","text":"Sound effects (SFX) are sounds made by monsters, spells, weapons etc. Sound effects are defined in multiple places, in .mds
files as part of the animation EventBlocks, or in the SFX Daedalus scripts. Sounds are located in the _work/Data/Sound/SFX
directory.
"},{"location":"zengin/sound/#speech","title":"Speech","text":"Dubbing for dialogues is located into _work/Data/Sound/Speech
folder. Every single AI_Output
has its own sound file with name defined in the function itself.
For this dialogue line
AI_Output(self,hero,\"Info_Diego_Gamestart_11_00\"); //I'm Diego.\n
the engine will play Info_Diego_Gamestart_11_00.wav
sound file (if it exists)."},{"location":"zengin/sound/tutorials/change_sfx/","title":"Changing Sound Effect","text":""},{"location":"zengin/sound/tutorials/change_sfx/#changing-sound-effect","title":"Changing Sound Effect","text":"This is Gothic VDFS. It is a tool that allows you to pack and unpack files in .VDF and .MOD format.
Let us start with unpacking \"Sound\" file:
In the \"(Viewer)\" tab, in the \"Filename\", go to your Gothic or Gothic II/Data folder and choose \"Sound.VDF\". Create a folder on your desktop or any other easily accessible place on your computer. Name it however you want. Go to \"Root path\" and choose the folder you just created. Press \"Extract volume\" if you want to unpack all sound files. The chosen file should be unpacking right now.
Here are the files we just extracted:
It can oftentimes be tricky to find the sound you are looking for, but we will leave that for later. Let's just see how can we change a sound file in the game now.
Get yourself any short sound file. In order for the sound to work in the game, it needs to be in mono .wav format. A lot of programs let you convert a file such as Audacity, so do just that; Rename your converted file into \"INV_CHANGE.WAV\" and replace it in SFX folder you just extracted; Go back to Gothic VDFS, go to (Builder) tab; In \"Filename\" you choose how do you want your file to be called and its location. I recommend creating separate folder and putting it there. You can also name the file however you want, as long as it has higher time stamp (more on that later) than original Sounds file. To create it as .VDF file, choose \"All file\" in the \"Save file as\" and call it \"Sounds.VDF\"; In \"Root path\" go to and choose \"_WORK\" folder; In the field just below \"Comment\", add a * character and then click on the + next to it; Press \"Build\", and if you did everything right, the folder is being packed back into .VDF file; That's how a successful process looks like:
Now get the file you just created, and put it in your Gothic/Data folder replacing the old one. The file we just replaced changes the sound in main menu and the inventory. If you can hear it, congratulations, you did it!
"},{"location":"zengin/textures/","title":"Textures","text":""},{"location":"zengin/textures/#textures","title":"Textures","text":"Textures are pictures that get projected onto 3D models and on a 2D user interface in the game. ZenGin uses its own texture format .TEX
, that actually is a container for the texture in one of available formats. This section will discuss how to work with textures in ZenGin.
Note
Technical documentation of the .TEX
texture format can be found in the ZenKit documentation.
"},{"location":"zengin/textures/#basics","title":"Basics","text":"All created textures have to be located in the _WORK\\DATA\\TEXTURES\\
directory. The compiled .TEX
files are saved in the _COMPILED\\
subdirectory.
Here are some tips for working with Gothic textures:
Textures must have dimensions that are multiples of 4. Square textures (with some exceptions, like faces or some interface elements) are preferred for easier mipmap generation. It is recommended not to use textures bigger than 4096x4096. Avoid things like _V0
, _A1
etc. in the texture name endings, as suffixes like this are used for multitextures. "},{"location":"zengin/textures/#formats","title":"Formats","text":"When working with textures in ZenGin, it is recommended to use the default texture format if you are unsure about other options. Many of the other formats are either unsupported or buggy in gothic. For transparency, DXT3
format should be used. For pure RGB colors, DXT1
format is recommended.
Tip
Formats like RGBA8888
, BGRA8888
, ARGB8888
and ABGR8888
are properly supported with the zSurface32 patch. Learn more about it in the 32 Bit texture support article.
"},{"location":"zengin/textures/#mipmaps","title":"Mipmaps","text":"Mipmaps are pre-generated versions of textures at different levels of detail. They are used, to improve rendering performance and reduce aliasing artifacts. When engine converts the texture it automatically generates mipmaps. Other tools may handle it differently, so it's better to check it before conversion.
How it works?
If you want to learn more about mipmaps in ZenGin there is a great article by Gothic Reloaded Mod Team.
"},{"location":"zengin/textures/#engine-compilation","title":"Engine compilation","text":"By default, .tga
files with a proper resolution are converted to .TEX
files by the engine, when they appear in the game or a game is started with -convertall
parameter. Also, you can convert textures to .TEX
manually using one of the available tools.
The engine compilation may be affected by keywords in the texture name or directory.
Color depth
Textures are compiled by default with a color depth of 16 bits per pixel and needs 4 bits of memory per pixel. To force the engine to convert textures with a different color depth, you need to add an ending to the name of the texture or directory _16BIT
or _32BIT
. Using 16/32 bit images makes sense when there are visual problems or noise after compression, but they take up more memory.
Example: _WORK\\DATA\\TEXTURES\\SKY\\NOMIP_16BIT\\CLOUDS.TGA
.
nomip
By default, Mipmaps are generated for all textures. However, if the texture path contains the directory nomip
, then a Mipmap will not be created for such a texture. It makes sense to use if you experience visual problems or interference associated with the use of Mipmaps, and also to save memory if the texture is rarely used in the game, or the texture is too small.
Example: _WORK\\DATA\\TEXTURES\\EFFECTS\\NOMIP\\LIGHTNING.TGA
"},{"location":"zengin/textures/#tools","title":"Tools","text":"There are some tools created by the Gothic community, that simplify working with ZenGin textures.
"},{"location":"zengin/textures/#goman","title":"GoMan","text":"Oldest texture tool, created by PyroX. Has a good viewer, but there are already better alternatives.
Download
"},{"location":"zengin/textures/#gotex","title":"GoTex","text":"Simple converter, written by ThielHater. Implements features like custom mipmaps and popular image formats support.
Thread on WoG
GitHub
"},{"location":"zengin/textures/#ztexipy","title":"zTEXiPy","text":"Latest tool, developed by Shoun. Offers batch conversion, an intuitive viewer, and Windows context menu shortcuts.
GitLab
"},{"location":"zengin/textures/32bit_texture/","title":"32 Bit texture support","text":""},{"location":"zengin/textures/32bit_texture/#32-bit-texture-support","title":"32 Bit texture support","text":"By default, ZenGin supports only compressed DXT1
and DXT3
textures. zSurface32 patch, created by Gratt improves texture quality by adding proper RGBA8888
, BGRA8888
, ARGB8888
and ABGR8888
format readout and DirectX 32 Bit surface support in ZenGin1 .
To use the patch you must have Union installed. Download the .patch
file here, and put it into system\\
directory.
Warning
It is advised to use BGRA8888
due to performance reasons, as other color spaces require additional conversion at runtime.
"},{"location":"zengin/textures/32bit_texture/#compilation","title":"Compilation","text":"ZenGin doesn\u2019t natively support the compilation of such textures. This can only be achieved using external programs. The simplest method to create a texture is by utilizing zTEXiPy.
Open your texture in zTEXiPy2 : Choose Save TEX as...
In this window: Uncheck Generate Mipmaps
if your texture is meant to be used as UI. Set the Colorspace
to BGRA8888 (zEnum:3)
or other supported format. Press Save
and check your texture in-game: "},{"location":"zengin/textures/32bit_texture/#but-why","title":"But why?","text":"This type of texture is compatible with any asset, whether it\u2019s armour or a sword. However, the primary application for such high-quality textures is in user interface elements, which make extensive use of gradients and the alpha channel:
BGRA8888 vs DXT3BGRA8888 vs DXT1
This example shows comparison between raw BGRA8888 color space and DXT3 (BC2)3 compression. DXT3 shows noticeable banding throughout entire texture wherever there's alpha channel, while BGRA8888 has smooth gradient transition.
This example shows comparison between raw BGRA8888 color space and DXT1 (BC1)3 compression. DXT1 shows lossy quantization artifacts, while BGRA8888 has none.
Source comparison files are available here.
The drawback of using these textures is their large size, as they contain uncompressed color data. However, this is a small price to pay for the improved quality of the final product.
Note
This article was originally written by Shoun and published on G2O Docs.
To learn more about ZenGin Textures reference click here.\u00a0\u21a9
zTEXiPy supports TGA, DDS, PNG and WEBP by default, so make sure it's one of those formats.\u00a0\u21a9
To learn more about DXTn Algorithm click here.\u00a0\u21a9\u21a9
"},{"location":"zengin/textures/multitextures/","title":"Multitextures","text":""},{"location":"zengin/textures/multitextures/#multitextures","title":"Multitextures","text":"Multitextures are used, for example, to create animation. For example, rippling water is represented by a sequence of textures WATER_A0.TGA
that can be applied to 3D geometry. Also in Gothic, multitextures are used to replace the texture of a character's body.
"},{"location":"zengin/textures/multitextures/#naming-convention","title":"Naming convention","text":"The naming convention for multitextures is as follows:
NAME_[Letter0][Number0]_..[LetterN][NumberN].TGA\n
Example: HUM_HEAD_HAIR1_C0_V0.TGA
In this way, multitextures are interconnected. The format is used exclusively for creating multitextures. Therefore, a name like w_s2_v1.TGA
to name only one texture is not allowed. The engine handles incorrect names, but not quickly.
"},{"location":"zengin/textures/multitextures/#body-textures","title":"Body textures","text":"Multitextures used for the body use two channels:
V - for skin variation C - for skin tone For example, the texture Hum_Body_Naked_V2_C3.tga
describes the body of a person without armor, variant 2, and skin tone 3 (Dark-skinned). Setting up specific character texture variations is determined in the script.
"},{"location":"zengin/tools/","title":"Tools","text":""},{"location":"zengin/tools/#tools","title":"Tools","text":"The community has developed many tools to help with the creation of Gothic mods.
Note
This list is a work in progress.
Daedalus
Daedalus Language Server - a VS Code/VS Codium extension that adds IDE like functionality for Daedalus scripting language Ikarus - A daedalus library for the game Gothic. Exploits the interpreter to allow arbitrary memory access and defines a lot of useful functions for interfacing with the engine. LeGo - A daedalus library for the game Gothic. It contains various packages to support modders. AFSP - Fawkes' & Auronen's script package for Gothic 1 and Gothic 2: Night of the Raven. Ninja - Ninja introduces the possibility of true modular modifications for the video games Gothic and Gothic 2 Night of the Raven. DecDat - Daedalus .DAT
files decompiler. Redefix - OutputUnits compiler and updater. VDFS tools
GothicVDFS - NicoDE's viewer, extractor and builder for .vdf
and .mod
volumes VDFS Tool - Gratt's Union VDFS viewer, extractor, builder, optimizer and ZIP compressor for .vdf
and .mod
volumes World Editors
Spacer - the original world editor for ZenGin, ships with the MDK Union Gothic World Editor - Saturas' world editor, supports new object classes created with Union Gothic World Editor - World editor for vanilla worlds, works with G1, G2 and G2 NotR worlds Spacer.NET - A modernised version of Spacer available as a Gothic Mod. Libraries
ZenKit - A library to load, save and use almost all ZenGin asset files Debugging
zSpy - Debugging tool that displays most of the operations performed by the engine during the Gothic or Spacer running, ships with the MDK. "},{"location":"zengin/tools/gothic_sourcer/","title":"Gothic Sourcer","text":""},{"location":"zengin/tools/gothic_sourcer/#gothic-sourcer","title":"Gothic Sourcer","text":"Gothic Sourcer can be used to do a lot of things.
Todo
TODO
"},{"location":"zengin/tools/zSpy/","title":"zSpy","text":""},{"location":"zengin/tools/zSpy/#zspy","title":"zSpy","text":"zSpy is a debugging tool that displays most of the operations performed by the engine during the Gothic or Spacer running.
Example image of running zSpy
Warning
zSpy must be started before Gothic or the Spacer is started so that the program can find it. Sometimes in Gothic I this has to be done manually, in Gothic II This is done by the GothicStarter_mod.
In order to be able to follow the messages in zSpy, Gothic should be started in the window. The corresponding startup option can be found in GothicStarter (mod). Within Gothic, when Marvin mode is activated, you can switch between window and full-screen mode at any time with the F3
key.
"},{"location":"zengin/tools/zSpy/#log-level","title":"Log Level","text":"With the -zlog#
command in GothicStarter, you can specify how many messages zSpy will output. #
can be a number between -1 and 9. Used for:
-1
- Disable every message (expect fatal errors)
0
- Shows only warnings, faults and fatal errors
1 - 9
- Display more information. Every Information has their priority. If you select 1, the program displays only messages with priority =< 1
, with 5 only priority =< 5
, and with 9, almost everything that Gothic can produce.
For general debugging, recommended value is 5.
"},{"location":"zengin/tools/zSpy/#output","title":"Output","text":"The zSpy issues its reports in the following form:
Time Type Priority User Message ... <filename, #line>\n00:21 Info: 3 B: GOTHIC: Exiting game ... .... <oGameManager.cpp,#617>\n
"},{"location":"zengin/tools/zSpy/#time","title":"Time","text":"Time elapsed since the start of Gothic.exe
"},{"location":"zengin/tools/zSpy/#type","title":"Type","text":"Type of message. The following message types are distinguished:
Fatal:
- Critical error causing application to close.
Fault:
- A simple bug that will not cause the application to stop, but display or performance issues may occur.
Warn:
- A warning of possible consequences. An error that follows soon afterwards could have something to do with it.
Info:
- General information about the progress of the program.
"},{"location":"zengin/tools/zSpy/#priority","title":"Priority","text":"Priority level of the message. Messages with lower priority (higher number) can be disabled. See log level.
"},{"location":"zengin/tools/zSpy/#user","title":"User","text":"User ID - a letter defined by every engine developer to highlight its logs
D
- Dieter U
- Ulf B
- Bert C
- Carsten A
- Andre X
- Kurt "},{"location":"zengin/tools/zSpy/#message","title":"Message","text":"The most important part. A message that contains:
Symbol representing a program module. The names are mostly self-explanatory, so there is no need to type them all (MDL
= 3D models, PAR
= Parser etc.).
The message for the user.
"},{"location":"zengin/tools/zSpy/#configuration","title":"Configuration","text":"In zSpy, you can customize the font and its color depending on the type of message.
In addition, you can configure the logging options:
Filtering various messages (Info, Warn, Fault, Fatal). Auto show/hide zSpy when starting/stopping Gothic. Saving the log file to a separate file. "},{"location":"zengin/tools/zSpy/#console-commands","title":"Console commands","text":"List of console commands related with zSpy.
Note
The list is work in progress. Console commands needs a separate article or section.
"},{"location":"zengin/tools/zSpy/#zerr-level","title":"zerr level
","text":"Sets a level of logging.
zerr level <#>\n
<#>
- max message priority. See log level. "},{"location":"zengin/tools/zSpy/#zerr-searchspy","title":"zerr searchspy
","text":"Links zSpy with Gothic. Useful when you run zSpy when the game is already running.
zerr searchspy\n
"},{"location":"zengin/tools/zSpy/#zerr-authors","title":"zerr authors
","text":"Sets a filter to display only messages of one author.
zerr authors <letter>\n
<letter>
- One of the letters listed here. "},{"location":"zengin/tools/zSpy/#zerr-rem","title":"zerr rem
","text":"Includes a remark into the log.
zerr rem\n
Looks like that: 00:46 Info: 3 B: OPT: Blood-Details: Value=2 .... <oGameManager.cpp,#1302>\n00:57 ---------------\n00:57 ---------------\n01:01 Info: 3 B: GMAN: Leaving Menu-Section .... <oGameManager.cpp,#1537>\n
"},{"location":"zengin/tools/zSpy/#zerr-status","title":"zerr status
","text":"Displays a current status of zSpy in the console.
zerr status\n
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/","title":"Daedalus Language Server","text":""},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#daedalus-language-server","title":"Daedalus Language Server","text":"Daedalus Language Server is a language server for Gothic's scripting language - Daedalus, created by Kirides. However, it is mostly known as VSCode extension, that is in fact named vscode-daedalus.
Warning
This article is focused on the vscode-daedalus extension, but since DLS uses Language Server Protocol it could be implemented into other editors.
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#installation","title":"Installation","text":" Download the.vsix File: Navigate to the latest release page of the vscode-daedalus repository on GitHub. Download the .vsix
file associated with the latest version available.
Open VSCode: Launch Visual Studio Code on your computer.
Access Extensions Tab: Go to the Extensions view in VSCode. You can do this by clicking on the square icon on the sidebar or pressing Ctrl+Shift+X
.
Install from VSIX: Click on the three dot icon located in the top right corner of the Extensions view to open the More Actions menu. Select the \"Install from VSIX...\" option.
Select the.vsix File: A file dialog will appear asking for the path to the .vsix
file you downloaded earlier. Navigate to the location where you saved the .vsix
file, select it, and confirm the selection.
Installation Process: VSCode will then proceed to install the Daedalus Language Server extension from the .vsix
file. Once the installation is complete, you may need to reload VSCode to activate the new extension.
Verify Installation: After reloading, check the Extensions view again to ensure that the Daedalus Language Server extension has been successfully installed.
"},{"location":"zengin/tools/daedalus_tools/daedalus_language_server/#setup","title":"Setup","text":"Before opening a project there are some setting that have to be changed. The table below shows which CodePage you should use according to your language.
CodePage Languages windows-1250 Czech, Polish, Hungarian, Romanian windows-1251 Russian, Ukrainian windows-1252 German, English, French, Italian, Spanish windows-1254 Turkish By default, DLS use windows-1252 encoding, if you want to change you have to edit the settings.json
file.
Open the Command Palette by pressing Ctrl+Shift+P
. Type settings.json
and select the option that appears, usually labeled \"Preferences: Open User Settings (JSON)\". Add the following lines at the end of the file (but before }
), replacing \"Windows-1250\" with the appropriate code page for your language: \"daedalusLanguageServer.fileEncoding\": \"Windows-1250\",\n\"daedalusLanguageServer.srcFileEncoding\": \"Windows-1250\",\n\"[daedalus]\": {\n \"files.encoding\": \"windows1250\"\n}\n
Now if you open a directory that contains e.g. GOTHIC.SRC
file, the extension will parse it and give you all Language Server features.
"},{"location":"zengin/tools/daedalus_tools/decdat/","title":"DecDat","text":""},{"location":"zengin/tools/daedalus_tools/decdat/#decdat","title":"DecDat","text":"DecDat1 is a daedalus scripts decompiler orginaly created by Gottfried. Its goal is to replace Gothic Sourcer's decompiler, which wouldn't been able to decompile scripts with Ikarus and LeGo. However, that doesn't mean that DecDat is able to produce data that can be compiled again. This tool should be used mainly for research and educational purposes. Source code is available here.
"},{"location":"zengin/tools/daedalus_tools/decdat/#instalation","title":"Instalation","text":"The tool is written in Java, allowing it to be executed seamlessly on both Windows and Linux operating systems. To utilize the tool, ensure that Java is installed on your system. We recommend using the Java version available here. Once you have your Java installed, download the latest tool version from GitHub releases page, and run the DecDat.jar
file.
"},{"location":"zengin/tools/daedalus_tools/decdat/#usage","title":"Usage","text":"After opening a DecDat you will see a following window.
To import a .DAT
file click at File -> Open DAT...
select the file encoding, the file itself and optionally OU.BIN
file if you want to parse dialogues.
And that's it, now you have a .DAT
file loaded into app, and you can export the code or search for a specific part.
The original DecDat release post can be found here.\u00a0\u21a9
"},{"location":"zengin/tools/libraries/zenkit/","title":"ZenKit","text":""},{"location":"zengin/tools/libraries/zenkit/#zenkit","title":"ZenKit","text":"ZenKit is a C++-library for loading and saving proprietary ZenGin files and is intended to be a successor to Andre Taulien's ZenLib. ZenKit wrappers for Java and C# are also available in the form of ZenKitCS and ZenKit4J which are also published to NuGet and Maven Central respectively.
ZenKit is used as the file loading and scripting backend for OpenGothic and has recently found adoption in GothicVR.
"},{"location":"zengin/tools/libraries/zenkit/#file-support","title":"File Support","text":"The following file types and operations are supported by ZenKit. Requests to support additional file types are welcome and can be submitted to the GitHub repository.
File Type Extension Load1 Save2 Comment Model Animation .MAN
\u2713 Yes \u2718 No \u2014 Model Hierarchy .MDH
\u2713 Yes \u2713 Yes \u2014 Model Mesh .MDM
\u2713 Yes \u2713 Yes Saving is only partially supported Model .MDL
\u2713 Yes \u2713 Yes Saving is only partially supported Morph Mesh .MMB
\u2713 Yes \u2718 No \u2014 Multi Resolution Mesh .MRM
\u2713 Yes \u2713 Yes \u2014 Mesh .MSH
\u2713 Yes \u2713 Yes Saving is only partially supported Daedalus Script .DAT
\u2713 Yes \u2718 No A VM implementation is available (see Daedalus VM) Texture .TEX
\u2713 Yes ~ Yes There is currently no API to alter image data Font .FNT
\u2713 Yes \u2713 Yes \u2014 ZenGin Archive .ZEN
\u2713 Yes \u2713 Yes \u2014 Text/Cutscenes .BIN
, .CSL
, .DAT
, .LSC
\u2713 Yes \u2713 Yes \u2014 Model Script .MDS
, .MSB
\u2713 Yes \u2718 No \u2014 Virtual File System .VDF
\u2713 Yes \u2713 Yes Allows full integration with the host file system"},{"location":"zengin/tools/libraries/zenkit/#daedalus-vm","title":"Daedalus VM","text":"Along facilities to read and write most resource files you might find in a typical Gothic installation, ZenKit also includes a virtual machine which can execute Daedalus scripts. An extensive API is available to inspect the files, add external handlers and bind Daedalus classes into C++-structs. Bindings for the original classes are available as an extension to ZenKit and available to the C# and Java wrappers natively.
"},{"location":"zengin/tools/libraries/zenkit/#documentation","title":"Documentation","text":"Additional documentation for ZenKit can be found at zk.gothickit.dev.
ZenKit is able to fully load these files\u00a0\u21a9
ZenKit is able to save these files at least partially\u00a0\u21a9
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/","title":"GothicVDFS","text":""},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#gothicvdfs","title":"GothicVDFS","text":"Gothic VDFS is the most popular VDFS tool. It was created by NicoDE and allows viewing, extracting and building .vdf
and .mod
archives.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#download","title":"Download","text":"You can download the tool from NicoDE's website - direct link.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#working-areas","title":"Working areas","text":"GothicVDFS has two working areas one for viewing volumes and one for building volumes.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#viewer","title":"Viewer","text":"This is a blank VDFS viewer:
There are two paths to choose at the top:
Filename - Path of the currently opened .vdf
or .mod
archive Root Path - Path to the place where the files will be extracted When you specify the Filename
the VDFS will load the volume and display some information.
Comment is an information about loaded volume left by the author.
Timestamp is a date and time set by the author. Usually the date coincides with the actual date of the volume's build, but it cannot be taken for granted as it can be easily changed.
Tip
The timestamp defines order of loading volumes into the game. Volumes with the latest timestamp are loaded first.
At the bottom there are three different options for extracting files from archive:
Extract Volume - extract the whole volume to the Root Path Extract Directory - extract only selected folder Extract Selected - extract currently selected files In addition, you can choose if files should keep their structure after extraction or get extracted directly to the Root Path.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#builder","title":"Builder","text":"The second working area is the Builder. It allows you to create new VDF archives.
That's how initial builder looks like:
There are two paths to choose at the top:
Filename - Path of the new .vdf
or .mod
archive Root Path - Path to the Gothic directory In the middle there are three areas in which you can specify archive files.
File(mask)(s) to search for - list of file masks to load in VDF archive e.g. _WORK/Data/Anims/_compiled/*
File(mask)(s) to exclude - list of file masks to exclude File(mask)(s) to include - list of file masks to include At the bottom there are three buttons:
Open Script - open a .vm
script file with VDF configuration Save Script - save current VDF configuration to a .vm
script file Build Volume - build the VDF archive with current configuration Example build configuration could look like this:
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#cli-interface","title":"CLI Interface","text":"CLI interface is very simple and allows building and extracting VDF archives without GUI. That's good for automation and scripting.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#build-vdf-from-script","title":"Build VDF from script","text":"GothicVDFS.exe /B script.vm\n
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#extract-vdf-to-directory","title":"Extract VDF to directory","text":"GothicVDFS.exe /X MySuperMod.mod ./extract_here\n
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#script-reference","title":"Script Reference","text":"GothicVDFS uses simple script language to define VDF archives. The script is a simple text file with .vm
extension. The script is divided into sections, each section is marked by a header in square brackets. The script must contain at least [BEGINVDF]
and [ENDVDF]
sections.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#beginvdf","title":"[BEGINVDF]
","text":"Marks the start of script and contains VDF properties.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#comment","title":"Comment
","text":"Comment of VDF archive. Equivalent of \"Comment\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#basedir","title":"BaseDir
","text":"Root path of local files (relative to working directory). Equivalent of \"Root Path\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#vdfname","title":"VDFName
","text":"Name of final VDF file (relative to working directory). Equivalent of \"Filename\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#files","title":"[FILES]
","text":"List of file masks to load in VDF archive (relative to BaseDir). Equivalent of \"File(mask)(s) to search for\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#exclude","title":"[EXCLUDE]
","text":"List of file masks to exclude. Equivalent of \"File(mask)(s) to exclude\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#include","title":"[INCLUDE]
","text":"List of file masks to include. Equivalent of \"File(mask)(s) to include\" from GUI.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#endvdf","title":"[ENDVDF]
","text":"Marks end of file.
"},{"location":"zengin/tools/vdfs_tools/gothic_vdfs/#example-script","title":"Example script","text":"example.vm[BEGINVDF]\nComment=Some VDFS archive\nBaseDir=.\nVDFName=SuperMod.mod\n[FILES]\n_work/Data/Anims/_compiled/*\n_work/Data/Meshes/_compiled/*\n_work/Data/Scripts/_compiled/*\n[EXCLUDE]\n*.wav\n[INCLUDE]\nthis_is_fine.wav\n[ENDVDF]\n
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/","title":"VDFS Tool","text":""},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#vdfs-tool","title":"VDFS Tool","text":"VDFS Tool1 is a new program that supports new features introduced to VDFS by the Union team. Like ZIP compression or drag and drop support.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#download","title":"Download","text":"You can download the tool using the Resource Manager or directly from the post on WoP.ru - VDFS Tool.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#features","title":"Features","text":""},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#volume-compression","title":"Volume compression","text":"Volumes are compressed using the classic zip algorithm. The zlib library for buffer compression and decompression was taken as a basis. In order for the game to decompress the volume in real time without loss of performance, a special interface Gratt-5r2/ZippedStream was implemented and built into vdfs32g
. The essence of the interface is that it allows you to pack and read files in blocks of a given size and keep unpacked data in memory in a specific range.
Warning
Compresed .mod
and .vdf
archives works only with Union installed.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#volume-optimization","title":"Volume optimization","text":"Optimization refers to the procedure of identifying files with the same content and combining them under a common data source.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#file-explorer-interface","title":"File Explorer Interface","text":"The program interface has a set of standard file explorer operations - copying, pasting, renaming, searching, etc.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#dragdrop","title":"Drag&Drop","text":"The function allows you to drag files into the program, as well as pull them out of it. For this function to work correctly, user (administrator) rights must match for the program and Explorer.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#updating-a-volume-in-1-click","title":"Updating a volume in 1 click","text":"The program analyzes shared files in the volume and in the game directories (Ctrl + U). If there are physical copies, when you save the volume, updated files will be written to it.
"},{"location":"zengin/tools/vdfs_tools/vdfs_tool/#opening-files-directly-from-a-volume","title":"Opening files directly from a volume","text":"To avoid wasting time unpacking the volume, double-click on the file of interest, after which it will be opened.
This is mostly a translation of the orginal release post.\u00a0\u21a9
"},{"location":"zengin/union/","title":"Union","text":""},{"location":"zengin/union/#union","title":"Union","text":"Union is a system to patch and extend Gothic's engine the ZenGin. It allows you to load .dll
files - ZenGin extensions created using the Gothic/Union SDK and .patch
files - files designed to patch the game's executable. The Union installer also contains the SystemPack a collection of bug fixes and engine edits that improve performance.
"},{"location":"zengin/union/#plug-ins","title":"Plug-ins","text":"Union plugins are shipped in the form of a .dll
library. This library contains the compiled C++ code with the Union SDK and an embedded .patch
file.
"},{"location":"zengin/union/#union-sdk--gothic-api","title":"Union SDK & Gothic API","text":"Union software development kit is a collection of tools and the Gothic API that allow you to create Union plugins and alter the engine's behavior. Gothic API is a set of 4 interfaces (each for one different ZenGin version) that allow you to interface with the engine, access the engine objects, change their behavior and introduce new classes and functionality.
"},{"location":"zengin/union/#patch-file-format","title":"PATCH file format","text":"The .patch
file contains one or more small programs that are designed to change the engine code (game executable). This is usually done to fix bugs. Union plug-ins contain an embedded .patch
file and this file usually contains changes to the binary necessary for the proper function of the plug-in.
"},{"location":"zengin/union/patch/","title":"Patch files","text":""},{"location":"zengin/union/patch/#patch-files","title":"Patch files","text":".patch
files are scripts that are used to change memory values or committing some actions when starting the engine. Files patches are launched from any directories monitored by the file system (System, Saves, _Work and any others at the request of the engine). The launch is performed both from physical directories and from VDF & MOD. If physical and virtual directories contain identical patches with identical paths, physical copies will have read priority.
Info
An additional [patch name] .MAP file can be created. This happens when the patch file has at least one patch marked 'static' (see the description of the patch format for more details). This file allows you to immediately download all previously made changes to process memory, skipping re-parsing of static blocks. By default, the file cannot be seen through standard files explorer. To make the file hidden, but visible, set the value SystemPack.ini -> ShowHiddenFiles = true.
Description of the patch format
"},{"location":"zengin/union/plugins/","title":"Union Plugins","text":""},{"location":"zengin/union/plugins/#union-plugins","title":"Union Plugins","text":"Plugins are libraries dynamically loaded via Union. They can be used to modify the behavior of the game, add new features, and fix bugs. Plugins are written in C++ and compiled into DLL files. The Union SDK and Gothic API provide a set of functions and classes that can be used to create plugins.
Warning
The plugin system is also a potential source of errors. If the plugin is written incorrectly, it can cause the game to crash or behave incorrectly. Therefore, when using plugins, you should be careful and follow the instructions of the plugin authors.
"},{"location":"zengin/union/plugins/#loading","title":"Loading","text":"Loading can be done both Physically and from VDF or MOD volumes. There are three options for loading libraries:
"},{"location":"zengin/union/plugins/#systempackini","title":"Systempack.ini","text":"The classic way is to specify the list of library names in SystemPack.ini -> PluginList separated by commas. Also through this parameter you can control the priority of launching plugins:
If you specify two asterisks (plugin.dll**) at the end of the library name, then it will be loaded earlier than the Virtual file system. But in this case it cannot be loaded from VDF or MOD volume.
If you specify one asterisk (plugin.dll*) at the end of the library name, then it will be launched immediately after the Virtual file system. At this stage the library can be loaded from VDF or MOD volume.
If the name of the library is specified without changes (plugin.dll), then it will be loaded simultaneously with the game. At this stage libraries have the ability to use global instances of Gothic classes.
"},{"location":"zengin/union/plugins/#autorun","title":"Autorun","text":"If the library is located in the Physical Directory System/Autorun
or in the Virtual Directory */Autorun
, then the library will be loaded along with the engine, as in step 1.III. In current versions of Union, the order of loading plugins from this folder is determined by the dependencies of the libraries on each other. This means that if one plugin imports symbols from another, then the Exporting will be loaded first, and then the Importing.
"},{"location":"zengin/union/plugins/#patch-file","title":"Patch File","text":"The patch files start automatically. This means that plugins can also run patches along with them. There are two script functions: LoadLibrary(\"plugin.dll\")
and LoadPlugins(\"plugin1.dll\", ..., \"pluginN.dll\")
.
"},{"location":"zengin/union/plugins/zSplitDialogs/","title":"zSplitDialogs","text":""},{"location":"zengin/union/plugins/zSplitDialogs/#zsplitdialogs","title":"zSplitDialogs","text":"Union plugin created by Top Layer, which gives possibility to extract dialogues from compiled scripts. That could be useful for creating dubbing, especially if you want to know which dialogues are voiced and which are not.
Download
Source code
"},{"location":"zengin/union/plugins/zSplitDialogs/#usage","title":"Usage","text":" Install Union 1.0l+ (zParserExtender is needed - it is inside Union since 1.0l version) Make sure zParserExtender is enabled in SystemPack.ini
[CORE]\nParserExtenderAlwaysOn = true\n
Put zSplitDialogs.vdf
into Data\\
directory Start game After this steps .txt
file with dialogues will be created in Dialogs\\
directory.
Example of a plugin output
"},{"location":"zengin/union/plugins/zSplitDialogs/#configuration","title":"Configuration","text":"At first run, in gothic.ini
will be created following section:
[ZSPLITDIALOGS]\nUnvoicedOnly=0\n
You can change value to 1
to receive only unvoiced subtitles.
"},{"location":"zengin/union/plugins/zbassmusic/","title":"zBassMusic","text":""},{"location":"zengin/union/plugins/zbassmusic/#zbassmusic","title":"zBassMusic","text":"zBassMusic is a modern music system for Gothic games based on ZenGin. It replaces the original DirectMusic system with a custom engine built on top of BASS Library to provide easier workflow for composers and additional functions for the perfect soundtrack design.
Info
The plugin has its very own docuentation site, if you are interested in including zBassMusic into your project see the detailed User Guide.
Contacts Authors Silver Ore Team - tehe GitHub zBassMusic Discord Gothic Modding Community server"},{"location":"zengin/union/plugins/zbassmusic/#features","title":"Features","text":" Direct playback of common audio formats (WAV, OGG, MP3) instead of DirectMusic proprietary formats Out-of-the-box support for existing music theme definitions (just change the audio file) Alternative scheduling & transition systems to support smooth cross-fades between themes Loading of music files from VDF volumes (DirectMusic required physical files) Scriptable interface for controlling the system from Deadalus scripts Backward compatibility with original .sgt
music (it's redirected to the DirectMusic system) "},{"location":"zengin/union/plugins/zgamepad/","title":"zGamePad","text":""},{"location":"zengin/union/plugins/zgamepad/#zgamepad","title":"zGamePad","text":"zGamePad plugin adds gamepad support for ZenGin games.
Important
Visit the excellent original GitHub wiki page.
Contacts Author Gratt GitHub zGamePad Forum zGamePad"},{"location":"zengin/union/plugins/zgamepad/#gamepad-support","title":"Gamepad support","text":" All xinput compatible (including emulators) Xbox controller family Dualshock 4 Dualsense Nintendo Switch Joy-Cons Nintendo Switch Pro Controller "},{"location":"zengin/union/plugins/zgamepad/#features","title":"Features","text":" Natural Movements Intuitiveness and smoothness of movement controls is the main goal of this plugin. Touch the world of Gothic with your hands. Interactive hints Interactive hints will help you in mastering the controls. You can always customize their appearance or disable them. Quick access The plugin has two quick access rings - **weapons and items. Use them to always have access to your items. Automatic save naming Sit comfortably. You do not have to reach for your keyboard, because the plugin itself will give a name to your saves. Saves rotation The best alternative to quicksaves for gamepad controls. Vibration response Immerse yourself in the game even more. Vibration will allow you to feel your character and everything that happens in the world. Target locking The plugin will always help you win. Keeping the enemy in focus will allow you to fight much more effectively. Stuck protection Oops! If you get stuck, hold both analogue sticks for a few seconds and the character will reset. "},{"location":"zengin/union/plugins/zgamepad/controls/","title":"Gamepad controls","text":""},{"location":"zengin/union/plugins/zgamepad/controls/#gamepad-controls","title":"Gamepad controls","text":"The zGamePad plugin comes with a default control scheme, but it is possible to create your own. The plugin will search for any file with the .gamepad.overlay
extension placed in Gothic/System
directory or in any of the loaded .mod
and .vdf
archives.
"},{"location":"zengin/union/plugins/zgamepad/controls/#control-file-syntax","title":"Control file syntax","text":"Gamepad controls are set using the .gamepad
configuration file. This file encodes the controls for different actions in the game and the hint string in multiple languages.
Warning
The .gamepad
file must be encoded in Unicode or UTF-8 to accommodate the multilingual hint strings.
"},{"location":"zengin/union/plugins/zgamepad/controls/#regions","title":"Regions","text":"The format supports code blocks specified by the #region
and #endregion
keywords. These regions do not have any syntactical meaning, they only offer a convenient way to collapse sections of the code in editors with the syntax highlighting capabilities such as Notepad++
Regions#region strings\n // TODO\n#endregion\n\n#region fight scheme\n // TODO\n#endregion\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#comments","title":"Comments","text":"Comments are useful for quick information or just to disable some old code that might come in handy later. The .gamepad
file syntax supports C++ line comments using two forward slashes //
.
Warning
Comments can only be used at the start of any given line!
Comments// this is a comment\nKeyRecord // this is NOT a comment\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#strings","title":"Strings","text":"Strings are used for interactive hints. They should be defined at the top of the file. To define a string, use the keyword String
. Strings have the following format:
Multilang string syntaxString [id]\n [langTag] [text]\n [langTag] [text]\n [langTag] [text]\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#example","title":"Example","text":"String interact\n Rus \"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c\"\n Eng \"Interact\"\n Pol \"Interakcja\"\n Deu \"Interagieren\"\n\nString remove_weapon\n Rus \"\u0423\u0431\u0440\u0430\u0442\u044c \u043e\u0440\u0443\u0436\u0438\u0435\"\n Eng \"Remove weapon\"\n Pol \"Chowanie broni\"\n Deu \"Waffe entfernen\"\n
The string name
must be unique and is used to reference the string while defining hints. The language tag matches the language in SystemPack.ini
. If the file does not contain the user's language, English will be taken by default. If there is no English, then the first one."},{"location":"zengin/union/plugins/zgamepad/controls/#control-bindings","title":"Control bindings","text":"A binding is a description of an event that includes emulation object and conditions. Hints are part of the binding. The general structure of the bind starts with the keyword KeyRecord
and has the following format:
Control bindingKeyRecord [modifier]\n Id [key name]\n Combination [gamepad keys]\n Emulation [engine logical and absolute keys]\n Condition [engine logical, absolute keys or logical functions]\n Help [name of the hint string]\n
Tip
All operators are optional! This means that if a binding should only show a hint, it doesn't have to contain Combination.
"},{"location":"zengin/union/plugins/zgamepad/controls/#example_1","title":"Example","text":"Control binding examplesKeyRecord\n Id StopUsingPicklock\n Combination JOY_B\n Emulation KEY_DOWN\n Condition Cond_InterfaceIsOpen, Cond_UsesPicklock, !JOY_B\n\nKeyRecord Toggled\n Id ReturnToHumanForm\n Combination JOY_A\n Emulation KEY_RETURN\n Condition Cond_InTransformation\n Help end_transform\n\nKeyRecord\n Id QuickRingSelectSlot\n Combination JOY_RSTICK_FULL\n Condition !Cond_InventoryIsOpen, Cond_IsOverlayTop\n Help focus_item\n
"},{"location":"zengin/union/plugins/zgamepad/controls/#controls-override","title":"Controls override","text":"If you want to change or remove bindings from another controls file, use the KeyDisable
keyword. Default controls file
Controls override syntaxKeyDisable [fileName].[Id]\n
Where fileName
is the name of the controls file without extension and id
is a key of the binding."},{"location":"zengin/union/plugins/zgamepad/controls/#example_2","title":"Example","text":"Controls override example// remove key from the main controls file\nKeyDisable Controls.ArrowDown\n\n// create new key based on the same buttons\nKeyRecord Toggled\n Id ArrowDownNew\n Combination JOY_DOWN\n Emulation GAME_DOWN\n
"},{"location":"zengin/union/plugins/zgamepad/keys_engine_absolute/","title":"Engine absolute keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_engine_absolute/#engine-absolute-keys","title":"Engine absolute keys","text":"Absolute keys are the physical keys on your keyboard.
MOUSE_DX\nMOUSE_DY\nMOUSE_UP\nMOUSE_DOWN\nMOUSE_LEFT\nMOUSE_RIGHT\nMOUSE_WHEELUP\nMOUSE_WHEELDOWN\nMOUSE_BUTTONLEFT\nMOUSE_BUTTONRIGHT\nMOUSE_BUTTONMID\nMOUSE_XBUTTON1\nMOUSE_XBUTTON2\nMOUSE_XBUTTON3\nMOUSE_XBUTTON4\nMOUSE_XBUTTON5\nKEY_ESCAPE\nKEY_1\nKEY_2\nKEY_3\nKEY_4\nKEY_5\nKEY_6\nKEY_7\nKEY_8\nKEY_9\nKEY_0\nKEY_MINUS\nKEY_EQUALS\nKEY_BACK\nKEY_TAB\nKEY_Q\nKEY_W\nKEY_E\nKEY_R\nKEY_T\nKEY_Y\nKEY_U\nKEY_I\nKEY_O\nKEY_P\nKEY_LBRACKET\nKEY_RBRACKET\nKEY_RETURN\nKEY_LCONTROL\nKEY_A\nKEY_S\nKEY_D\nKEY_F\nKEY_G\nKEY_H\nKEY_J\nKEY_K\nKEY_L\nKEY_SEMICOLON\nKEY_APOSTROPHE\nKEY_GRAVE\nKEY_LSHIFT\nKEY_BACKSLASH\nKEY_Z\nKEY_X\nKEY_C\nKEY_V\nKEY_B\nKEY_N\nKEY_M\nKEY_COMMA\nKEY_PERIOD\nKEY_SLASH\nKEY_RSHIFT\nKEY_MULTIPLY\nKEY_LMENU\nKEY_SPACE\nKEY_CAPITAL\nKEY_F1\nKEY_F2\nKEY_F3\nKEY_F4\nKEY_F5\nKEY_F6\nKEY_F7\nKEY_F8\nKEY_F9\nKEY_F10\nKEY_NUMLOCK\nKEY_SCROLL\nKEY_NUMPAD7\nKEY_NUMPAD8\nKEY_NUMPAD9\nKEY_SUBTRACT\nKEY_NUMPAD4\nKEY_NUMPAD5\nKEY_NUMPAD6\nKEY_ADD\nKEY_NUMPAD1\nKEY_NUMPAD2\nKEY_NUMPAD3\nKEY_NUMPAD0\nKEY_DECIMAL\nKEY_OEM_102\nKEY_F11\nKEY_F12\nKEY_F13\nKEY_F14\nKEY_F15\nKEY_KANA\nKEY_ABNT_C1\nKEY_CONVERT\nKEY_NOCONVERT\nKEY_YEN\nKEY_ABNT_C2\nKEY_NUMPADEQUALS\nKEY_PREVTRACK\nKEY_AT\nKEY_COLON\nKEY_UNDERLINE\nKEY_KANJI\nKEY_STOP\nKEY_AX\nKEY_UNLABELED\nKEY_NEXTTRACK\nKEY_NUMPADENTER\nKEY_RCONTROL\nKEY_MUTE\nKEY_CALCULATOR\nKEY_PLAYPAUSE\nKEY_MEDIASTOP\nKEY_VOLUMEDOWN\nKEY_VOLUMEUP\nKEY_WEBHOME\nKEY_NUMPADCOMMA\nKEY_DIVIDE\nKEY_SYSRQ\nKEY_RMENU\nKEY_PAUSE\nKEY_HOME\nKEY_UP\nKEY_PRIOR\nKEY_LEFT\nKEY_RIGHT\nKEY_END\nKEY_DOWN\nKEY_NEXT\nKEY_INSERT\nKEY_DELETE\nKEY_LWIN\nKEY_RWIN\nKEY_APPS\nKEY_POWER\nKEY_SLEEP\nKEY_WAKE\nKEY_WEBSEARCH\nKEY_WEBFAVORITES\nKEY_WEBREFRESH\nKEY_WEBSTOP\nKEY_WEBFORWARD\nKEY_WEBBACK\nKEY_MYCOMPUTER\nKEY_MAIL\nKEY_MEDIASELECT\nKEY_BACKSPACE\nKEY_NUMPADSTAR\nKEY_LALT\nKEY_CAPSLOCK\nKEY_NUMPADMINUS\nKEY_NUMPADPLUS\nKEY_NUMPADPERIOD\nKEY_NUMPADSLASH\nKEY_RALT\nKEY_UPARROW\nKEY_PGUP\nKEY_LEFTARROW\nKEY_RIGHTARROW\nKEY_DOWNARROW\nKEY_PGDN\n
"},{"location":"zengin/union/plugins/zgamepad/keys_engine_logical/","title":"Engine logical keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_engine_logical/#engine-logical-keys","title":"Engine logical keys","text":"Logical keys are the keys you set in keyboard settings in the game menu. These can fill multiple roles in different situations and the gamepad controls can be set to emulate these logical keys.
GAME_LEFT\nGAME_RIGHT\nGAME_UP\nGAME_DOWN\nGAME_ACTION\nGAME_SLOW\nGAME_ACTION2\nGAME_WEAPON\nGAME_SMOVE\nGAME_SMOVE2\nGAME_SHIFT\nGAME_END\nGAME_INVENTORY\nGAME_LOOK\nGAME_SNEAK\nGAME_STRAFELEFT\nGAME_STRAFERIGHT\nGAME_SCREEN_STATUS\nGAME_SCREEN_LOG\nGAME_SCREEN_MAP\nGAME_LOOK_FP\nGAME_LOCK_TARGET\nGAME_PARADE\nGAME_ACTIONLEFT\nGAME_ACTIONRIGHT\nGAME_LAME_POTION\nGAME_LAME_HEAL\n
"},{"location":"zengin/union/plugins/zgamepad/keys_gamepad/","title":"Gamepad keys","text":""},{"location":"zengin/union/plugins/zgamepad/keys_gamepad/#gamepad-keys","title":"Gamepad keys","text":"In order to set gamepad keys, you have to know the key codes as they are listed below.
JOY_UP\nJOY_DOWN\nJOY_LEFT\nJOY_RIGHT\nJOY_MENU\nJOY_VIEW\nJOY_LSTICK\nJOY_RSTICK\nJOY_LB\nJOY_RB\nJOY_A\nJOY_B\nJOY_X\nJOY_Y\nJOY_LSTICK_LOWUP\nJOY_LSTICK_UP\nJOY_LSTICK_DOWN\nJOY_LSTICK_LEFT\nJOY_LSTICK_RIGHT\nJOY_RT\nJOY_LT\nJOY_DPAD\nJOY_UPDOWN\nJOY_LEFTRIGHT\nJOY_LSTICK_FULL\nJOY_RSTICK_FULL\n
"},{"location":"zengin/union/plugins/zgamepad/logical_functions/","title":"Logical function names","text":""},{"location":"zengin/union/plugins/zgamepad/logical_functions/#logical-function-names","title":"Logical function names","text":"Conditions for when to show or allow the control binding to work are specified using these logic functions. They describe different useful states of the game or user interface, allowing the user to set when will a certain control work.
Cond_FightMode - player is in the fight mode\nCond_FightModeMelee - player is in the melee fight mode\nCond_FightModeRange - player is in the ranged fight mode\nCond_FightModeMagic - player is in the magical fight mode\nCond_CanShoot - player is in the aim mode and can shoot now\nCond_CanSneaking - player is sneaking now\nCond_Diving - player is diving now\nCond_HasFocusVob - player has a focus vob\nCond_HasFocusNpc - player has a focus npc\nCond_OnChooseWeapon - weapon selection is active\nCond_InventoryIsOpen - inventory is open\nCond_InTransformation - player is transformed\nCond_VideoIsOpen - video is playing\nCond_CanLockTarget - player in the fight mode now and can lock the focus vob\nCond_G1 - this engine is a Gothic 1 (or sequel)\nCond_G2 - this engine is a Gothic 2 NoTR (or classic)\nCond_IsDialogTop - dialog window is open on the top\nCond_IsDocumentTop - document object is open on the top\nCond_IsOverlayTop - gamepad overlay object is open on the top\nCond_IsMenuTop - game menu is open on the top\nCond_OnSpellBook - magic selection ring is active\nCond_IsPlayerTalking - player is talking to someone\nCond_InterfaceIsOpen - open any interface element\nCond_HasLeftContainer - the left container is open (chest, plunder, trader)\nCond_UsesPicklock - player is picking a lock now\nCond_IsOnTrade - player is trading\nCond_IsOverlayTop - gamepad overlay object is open on the top\nCond_IsMenuTop - game menu is open on the top\n
"},{"location":"zengin/union/sdk/","title":"Union SDK","text":""},{"location":"zengin/union/sdk/#union-sdk","title":"Union SDK","text":"Union SDK is a software development kit for making Union plugins that directly interact with Gothic engines. It contains a project template for Visual Studio IDE, a C++ library for hooking into a Gothic executable, and Gothic API with methods' addresses for the engines of Gothic I, Gothic II, Gothic II NotR, and also for the not released Gothic Sequel.
Working with Union SDK requires at least basic knowledge of C++ programming. Knowledge of the x86 (32-bit) architecture, dynamically linked libraries, and reverse engineering is also welcomed as we need to understand what the Gothic engine does under the hood to use it effectively.
"},{"location":"zengin/union/sdk/#requirements","title":"Requirements","text":"Union SDK requires Visual Studio IDE, NET Framework 4.7.2, and Visual C++ 2010 libraries. They are available on Microsoft websites:
Visual Studio - https://visualstudio.microsoft.com/vs/ NET Framework 4.7.2 - https://dotnet.microsoft.com/download/dotnet-framework/net472 Visual C++ 2010 - https://www.microsoft.com/download/details.aspx?id=26999 "},{"location":"zengin/union/sdk/#resource-manager","title":"Resource Manager","text":"The official installation of Union SDK is provided through Resource Manager. After the installation, Visual Studio will have a new project template \"Union Plugin 1.0\" that creates a basic Union plugin project.
"},{"location":"zengin/union/sdk/events/","title":"Game Events","text":""},{"location":"zengin/union/sdk/events/#game-events","title":"Game Events","text":"Union defines several Game Events that are dispatched when a specific event occurs in-game. Handlers are defined in Plugin.cpp
and we can use them to execute our code during specific moments of the application lifetime.
"},{"location":"zengin/union/sdk/events/#events","title":"Events","text":""},{"location":"zengin/union/sdk/events/#initialization","title":"Initialization","text":""},{"location":"zengin/union/sdk/events/#game_entry","title":"Game_Entry","text":"Executes at the entry point of the Gothic executable. During this time the engine classes are not yet initialized, so using them may cause an access violation. The entry point be used to execute some logic before Gothic loads itself.
void Game_Entry() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_defineexternals","title":"Game_DefineExternals","text":"Executes before the Daedalus parser starts loading scripts. It's meant to define custom external functions.
void Game_DefineExternals() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_init","title":"Game_Init","text":"Executes right after DAT files are loaded and just before the main menu shows up.
void Game_Init() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#level-change","title":"Level Change","text":""},{"location":"zengin/union/sdk/events/#game_loadbegin","title":"Game_LoadBegin","text":"Executes when we initiate a level change by one of the possible actions. The default plugin template uses a common LoadBegin()
function to handle all events but we also can write different logic for different cases.
void LoadBegin() {\n\n}\n\n// When player clicks \"New Game\"\nvoid Game_LoadBegin_NewGame() {\n LoadBegin();\n}\n\n// When player loads a saved game\nvoid Game_LoadBegin_SaveGame() {\n LoadBegin();\n}\n\n// When player changes ZEN by a trigger\nvoid Game_LoadBegin_ChangeLevel() {\n LoadBegin();\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadend","title":"Game_LoadEnd","text":"Executes when the level loading finishes. The default plugin template uses a common LoadEnd()
function to handle all events but we also can write different logic for different cases.
void LoadEnd() {\n\n}\n\n// When player clicks \"New Game\"\nvoid Game_LoadEnd_NewGame() {\n LoadEnd();\n}\n\n// When player loads a saved game\nvoid Game_LoadEnd_SaveGame() {\n LoadEnd();\n}\n\n// When player changes ZEN by a trigger\nvoid Game_LoadEnd_ChangeLevel() {\n LoadEnd();\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadbegin_trigger","title":"Game_LoadBegin_Trigger","text":"Executes when the player enters a trigger that initiates ZEN change.
void Game_LoadBegin_Trigger() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_loadend_trigger","title":"Game_LoadEnd_Trigger","text":"Executes after the player has entered a trigger that initiates ZEN change.
void Game_LoadEnd_Trigger() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_applyoptions","title":"Game_ApplyOptions","text":"Executes after Game_LoadEnd
, when we save the game, and also when we exit the game. It's meant to be used to apply options from INI files.
void Game_ApplyOptions() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game-loop","title":"Game Loop","text":""},{"location":"zengin/union/sdk/events/#game_preloop","title":"Game_PreLoop","text":"Executes at the start of every frame.
void Game_PreLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_loop","title":"Game_Loop","text":"Executes at every frame.
void Game_Loop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_postloop","title":"Game_PostLoop","text":"Executes at the end of every frame.
void Game_PostLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_menuloop","title":"Game_MenuLoop","text":"Executes at every frame when the game menu is active.
void Game_MenuLoop() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_savebegin","title":"Game_SaveBegin","text":"Executes when the player started saving a game.
void Game_SaveBegin() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_saveend","title":"Game_SaveEnd","text":"Executes when the game save finishes.
void Game_SaveEnd() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_pause","title":"Game_Pause","text":"Executes when the player opens the in-game menu.
void Game_Pause() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#game_unpause","title":"Game_Unpause","text":"Executes when the player leaves the in-game menu and also when the player loads a saved game.
void Game_Unpause() {\n\n}\n
"},{"location":"zengin/union/sdk/events/#shutdown","title":"Shutdown","text":""},{"location":"zengin/union/sdk/events/#game_exit","title":"Game_Exit","text":"Executes when the player exits the game.
void Game_Exit() {\n\n}\n
"},{"location":"zengin/union/sdk/externals/","title":"Externals","text":""},{"location":"zengin/union/sdk/externals/#externals","title":"Externals","text":"Externals are functions defined by the Gothic engine that can be called from scripts. Union SDK provides symbols for pointers to global zCParser
instances that we can use to interact with the parser and to define a custom external function.
extern zCParser* parser;\nextern zCParser*& parserSoundFX;\nextern zCParser*& parserParticleFX;\nextern zCParser*& parserVisualFX;\nextern zCParser*& parserCamera;\nextern zCParser*& parserMenu;\nextern zCParser*& parserMusic;\n
"},{"location":"zengin/union/sdk/externals/#creating-custom-external","title":"Creating custom external","text":"To create an external we need to define a function handler and register it in the parser. Before we start, it's good to write down a Daedalus function signature so we can see the return and argument types that will be important later.
func string AddNumbers(var int FirstArgument, var int SecondArgument, var string ThirdArgument) {}\n
"},{"location":"zengin/union/sdk/externals/#function-handler","title":"Function handler","text":"External function handler signature must:
return int
or bool
use __cdecl
calling convention (default in C++) take no arguments Inside the handler, we can use the global parser
to pop function arguments and push the return value from/to the stack. It's important to pop the arguments in reverse order and to pop all of them even if we are not going to use them. Similarly, the return value must always be set if any and must never be set if the function returns void
. If we don't follow the rules, the stack may get corrupted and lead to the Gothic crash.
// __cdecl is optional because it's the default calling convention\nint __cdecl AddNumbers_External()\n{\n // Declare arguments\n int FirstArgument;\n int SecondArgument;\n zSTRING ThirdArgument;\n\n // Pop arguments from the stack **IN REVERSE ORDER**\n parser->GetParameter(ThirdArgument);\n parser->GetParameter(SecondArgument);\n parser->GetParameter(FirstArgument);\n\n // Execute function logic\n int result = FirstArgument + SecondArgument;\n zSTRING output = ThirdArgument + zSTRING(result);\n\n // Push return value\n parser->SetReturn(output);\n\n // Return value is ignored, so 0 or 1 is fine.\n return 0;\n}\n
"},{"location":"zengin/union/sdk/externals/#register-external","title":"Register external","text":"Externals should be registered in the parser during the Game_DefineExternals
game event. We need to call parser->DefineExternal
with variadic arguments:
external function name in Daedalus reference to function handler return type ...argument types zPAR_TYPE_VOID
indicates the end of the argument types list void Game_DefineExternals() {\n parser->DefineExternal(\"AddNumbers\", AddNumbers_External, zPAR_TYPE_STRING, zPAR_TYPE_INT, zPAR_TYPE_INT, zPAR_TYPE_STRING, zPAR_TYPE_VOID);\n}\n
Available types are defined by an enum:
enum {\n zPAR_TYPE_VOID,\n zPAR_TYPE_FLOAT,\n zPAR_TYPE_INT,\n zPAR_TYPE_STRING,\n zPAR_TYPE_CLASS,\n zPAR_TYPE_FUNC,\n zPAR_TYPE_PROTOTYPE,\n zPAR_TYPE_INSTANCE\n};\n
"},{"location":"zengin/union/sdk/getting_started/","title":"Getting Started","text":""},{"location":"zengin/union/sdk/getting_started/#getting-started","title":"Getting Started","text":"This article provides a beginner-friendly tutorial for setting up and compiling a Union project. Instructions for installing Union SDK are located at Union SDK.
"},{"location":"zengin/union/sdk/getting_started/#creating-union-plugin","title":"Creating Union plugin","text":""},{"location":"zengin/union/sdk/getting_started/#create-a-visual-studio-project","title":"Create a Visual Studio project","text":"To create a Union plugin project inside Visual Studio we need to use File -> New -> Project. On the next screen, we select \"Union Plugin 1.0m\", and click Next. For the project configuration, we should choose:
Key Value Project name eg. MyPlugin Location Directory where to store the source code Solution Create new solution Solution name eg. MyPlugin We will also check \"Place solution and project in the same directory\" because our plugin consists of only one project, so there is no need to complicate the file structure.
"},{"location":"zengin/union/sdk/getting_started/#file-structure","title":"File Structure","text":"Folder / File Description Engine\u00a0SDK/ In this folder, we have the Gothic Engine API in the form of header files. Most of the files between engines are very similar to each other but they can't be used interchangeably because each engine has slightly different API and addresses of functions. Engine\u00a0SDK/User\u00a0API/ These are empty files that are included in the corresponding engine headers. There are meant for placing additional methods extending classes that can be used for example in Hooks. Plugin/System/ DLL entry point generated by Union. We shouldn't modify anything here. Plugin/Workspace/Interface/ These are header files containing headers and source files important in correct order and an Interface.cpp
file that merges all the code into one file. Plugin/Workspace/Plugin/ Finally, this is the source code of the plugin and especially Plugin.cpp
where we can create code executed on Game Events."},{"location":"zengin/union/sdk/getting_started/#build-configuration","title":"Build Configuration","text":"Each Union plugin may target one or many versions of the Gothic engine and to select the proper API, Union SDK defines several build configurations for every engine, configuration, and also multiplatform build options. Each Target/Configuration combination is named [ENGINE] [CONFIGURATION]
.
Configurations:
Debug: Unoptimized build with debug symbols for development. MD Release: Optimized build for release versions. Runtime Library: Multi-threaded DLL (/MD) MT Release: Optimized build for release versions. Runtime Library: Multi-threaded (/MT) Engines:
G1: Gothic I G1A: Gothic Sequel G2: Gothic II G2A: Gothic II NotR MP x2: Multiplatform target for both Gothic I (G1) and Gothic II NotR (G2A) MP x4: Multiplatform target for all engine versions (Gothic I, Gothic Sequel, Gothic II, Gothic II NotR) For learning Union, it's suggested to select G2A Debug for Gothic II NotR or G1 Debug for Gothic I.
"},{"location":"zengin/union/sdk/getting_started/#project-configuration","title":"Project Configuration","text":"The Union plugin is a regular C++ Visual Studio project so it's possible to configure the project, compiler, linker, and debugger as we wish by going into Project -> Properties. For a starter, we should go to the General tab and check if Platform Toolset is installed and selected. If not, we should select one that's available on our system. Union was created with v100 but it also supports the newest toolkits, so it's best to select a modern one.
In the General tab, we can also specify the Output Directory where the plugin DLL will be placed after the build. During development, we can set it to <GOTHIC_DIR>/System/Autorun
where <GOTHIC_DIR>
is the root folder of the Gothic installation with Union that we will use for testing. Each DLL file placed in System/Autorun
is automatically loaded by Union runtime.
Another method is to put the DLL in the System
directory and modify Gothic.ini
to include
[PLUGIN]\n# Plugin file names without .dll \nPluginList = MyPlugin \n
"},{"location":"zengin/union/sdk/getting_started/#build-the-plugin","title":"Build the plugin","text":"After the initial configuration, we are ready to code something and see if our configuration is working. Let's collect some information about Union and display it with a MessageBox when the game starts. To do so, we locate the Plugin.cpp
file and put our logic in one of the Game Events handlers. The best for that is Game_Init()
because it's executed right after the engine loads every DAT file but before anything else:
void Game_Init() {\n const CPlugin* myPlugin = CPlugin::GetCurrentPlugin();\n\n CStringA gothicVersion;\n switch (Union.GetEngineVersion()) {\n case Engine_G1:\n gothicVersion = \"Gothic I\";\n break;\n case Engine_G1A:\n gothicVersion = \"Gothic Sequel\";\n break;\n case Engine_G2:\n gothicVersion = \"Gothic II\";\n break;\n case Engine_G2A:\n gothicVersion = \"Gothic II NoTR\";\n break;\n default:\n gothicVersion = \"Not possible case. Engine version doesn't match any known engine.\";\n break;\n }\n\n CStringA message = \"Plugin: \" + myPlugin->GetName() + \"\\n\";\n message = message + \"Union Version: \" + Union.GetUnionVersion().ToString() + \"\\n\";\n message = message + \"Gothic Version: \" + gothicVersion;\n\n Message::Info(message, \"Hello World\");\n}\n
Now we can Build (F7) the project to create the DLL. If we have set up Output Directory before, the plugin will deploy directly to the game. Otherwise, we can copy it manually from Bin
to <GOTHIC_DIR>/System/Autorun/MyPlugin.dll
. When we launch the game, a MessageBox should appear right before the main menu:
"},{"location":"zengin/union/sdk/getting_started/#couldnt-build-the-plugin","title":"Couldn't build the plugin?","text":"If you could not build the plugin or it crashed the game, you have to do some debugging and find the root cause of that. For compilation errors look at the Visual Studio Output tab and read the errors.
If they say something about missing toolset, make sure that you selected a Platform Toolset that's installed.
If the proper toolset is selected but doesn't work, make sure that you are configuring the same Configuration that is used for building.
If the plugin was built but the game crashed, you probably selected Configuration for the wrong platform. Gothic 2 Night of the Raven is G2A
and doesn't work with G2
or G1A
. If you are playing Gothic II Classic from Steam, please be advised that it still uses the Night of The Raven engine so the plugin must target G2A
.
"},{"location":"zengin/union/sdk/getting_started/#debugging","title":"Debugging","text":"Union plugins are regular DLLs with executable code hooked to Gothic.exe and running on it, so they can be debugged using the same techniques as any other software.
"},{"location":"zengin/union/sdk/getting_started/#visual-studio-debugger","title":"Visual Studio Debugger","text":"Visual Studio Debugger lets us set breakpoints on any line of code to stop the execution when we reach it. It also gives us a lot of information about the program state at this point. To use the debugger we only need to attach it to the Gothic.exe progress and compile the plugin with Debug configuration.
Option #1: Open Project -> Properties and in the Debugging tab, set Command to the path of our Gothic.exe. Then we can run \"Local Windows Debugger\" in Visual Studio and it starts Gothic with a debugger attached automatically.
Option #2: Open Debug -> Attach to process... and filter process list by \"Gothic\". Run the game separately and when the process appears in Visual Studio, select it and attach to it.
Caveats:
If we attach to the process early, we may get an \"Exception thrown at 0x7B11DB86 (Shw32.dll) in Gothic2.exe: 0xC0000005: Access violation writing location 0x00ABD000.\" right at the beginning. It's fine, just click Continue and Gothic will start properly. If a breakpoint hits when our cursor is locked by Gothic, we may not be able to get the cursor back until execution continues. In this case, we can still use Alt+Tab to switch to Visual Studio and use F5 to continue or F10 to step over. Disabling mouse support in the config may also fix this problem. "},{"location":"zengin/union/sdk/getting_started/#print-debugging","title":"Print Debugging","text":"Printing to some output is probably the simplest form of debugging and Union provides us with several choices.
"},{"location":"zengin/union/sdk/getting_started/#logging-to-zspy","title":"Logging to zSPY","text":"zSPY can be accessed using a global zerr
object. zSPY uses a message filtering system based on the first letter of the message, so our logs should follow the standard format used by other parts of ZenGine. Otherwise, the message may not be visible.
zerr->Message(\"X: MyPlugin: message to zSPY\");\n
"},{"location":"zengin/union/sdk/getting_started/#logging-to-union-console","title":"Logging to Union console","text":"Union console needs to be enabled inside SystemPack.ini
first:
[CORE]\nShowDebugWindow = true\n
Then we can use a global cmd
object behaving like C++ std::cout
to log into the Union console: cmd << \"message to Union console\";\n
"},{"location":"zengin/union/sdk/getting_started/#logging-to-visual-studio","title":"Logging to Visual Studio","text":"Visual Studio can also receive logs from our plugin using:
OutputDebugString(\"message to Visual Studio\");\n
This method works only when we have a debugger attached, so it's not recommended for general logging."},{"location":"zengin/union/sdk/hooks/","title":"Hooks","text":""},{"location":"zengin/union/sdk/hooks/#hooks","title":"Hooks","text":"Union provides a hooks system that lets us intercept calls to the engine functions and methods with our custom interceptor. To hook a function or method we need to know its address which can be acquired either from Engine SDK/[Engine]/Names_[Engine].hpp
or from the engine classes headers Engine SDK/[Engine]/Headers
.
"},{"location":"zengin/union/sdk/hooks/#intercepting-functions","title":"Intercepting functions","text":"To declare a hook we can use CInvoke
class or HOOK AS
macros.
CInvoke<function_type> Ivk_HookName(orignal_function_address, our_interceptor_function, hook_flags);\n\nHOOK Ivk_HookName AS(orignal_function_address, our_interceptor_function, hook_flags);\n
"},{"location":"zengin/union/sdk/hooks/#regular-functions","title":"Regular functions","text":"Regular functions are the functions declared outside of classes.
// 0x0042C450 int __cdecl Apply_Options_Video(void)\n\n// Forward declaration\nint Apply_Options_Video(); \n\n// Hook declaration\nCInvoke<int(*)()> Ivk_Apply_Options_Video(0x0042C450, &Apply_Options_Video);\n// Equivalent:\n// HOOK Ivk_Apply_Options_Video AS(0x0042C450, &Apply_Options_Video);\n\n// Implementation of interceptor\nint Apply_Options_Video() {\n Message::Info(\"Before original Apply_Options_Video()\");\n\n // Original function can be called using CInvoke pointer.\n int result = Ivk_Apply_Options_Video();\n\n Message::Info(\"After original Apply_Options_Video()\");\n\n return result;\n}\n
"},{"location":"zengin/union/sdk/hooks/#member-function","title":"Member function","text":"Member functions are the functions declared as non-static class members and they take a class instance pointer as an implicit first argument (__thiscall
calling convention). We can hook them in two ways using either a regular function or declaring a new method in User API.
"},{"location":"zengin/union/sdk/hooks/#option-1---regular-function","title":"Option #1 - Regular function","text":"// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &)\n\n// Forward declaration\nint __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context);\n\n// Hook declaration\nCInvoke<int(__fastcall *)(zCVob* _this, zTRenderContext& context)> Ivk_zCVob_Render(0x006015D0, &zCVob_Render);\n// Equivalent:\n// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob_Render);\n\n// Implementation of interceptor as regular function\n// Notice the first argument that's a pointer to class instance (this)\nint __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context) {\n if(_this == player) {\n screen->PrintCX(1000, \"Rendering a player zCVob\");\n }\n\n // Call original method\n return Ivk_zCVob_Render(_this, context);\n}\n
"},{"location":"zengin/union/sdk/hooks/#option-2---user-api","title":"Option #2 - User API","text":"In Engine SDK/User API
we can find a .inc
file for the class we are hooking and define a new member method there. In this case, we are looking for zCVob.inc
:
// Supported with union (c) 2020 Union team\n\n// User API for zCVob\n// Add your methods here\n\nint RenderUnion(zTRenderContext& context);\n
Then we can declare the hook pointing to our member method:
// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &)\n\n// Hook declaration\nCInvoke<int(__fastcall zCVob::*)(zTRenderContext& context)> Ivk_zCVob_Render(0x006015D0, &zCVob::RenderUnion);\n// Equivalent:\n// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob::RenderUnion);\n\n// Implementation of interceptor method\nint zCVob::RenderUnion(zTRenderContext& context) {\n if(this == player) {\n screen->PrintCX(1000, \"Rendering a player zCVob\");\n }\n\n // Call original method\n return Ivk_zCVob_Render(this, context);\n}\n
"},{"location":"zengin/union/sdk/hooks/#hook-flags","title":"Hook flags","text":"In the third argument of CInvoke
we can provide hook flags. The default value is IVK_AUTO
.
enum EInterMode\n{\n // Hook will not intercept the function.\n IVK_DISABLED = 1 << 1,\n\n // Normal hook. If other hook is already defined for the same address, an error pops up.\n IVK_NORMAL = 1 << 2,\n\n // Hook will automatically create an interception tree to allow multiple hooks for the same address.\n IVK_AUTO = 1 << 3,\n\n // Overrides any hook defined for the same address before.\n IVK_REDEFINE = 1 << 4,\n\n // Makes it impossible to override or disable the hook.\n // It should be used only in very specific cases.\n IVK_PROTECTED = 1 << 5,\n\n // Same as IVK_DISABLED\n IVK_READONLY = IVK_DISABLED\n};\n
"},{"location":"zengin/union/sdk/hooks/#credits","title":"Credits","text":"Examples are taken from the Union lessons in Russian created by Gratt on worldofplayers.ru/threads/41490/
"},{"location":"zengin/worlds/","title":"Worlds","text":""},{"location":"zengin/worlds/#worlds","title":"Worlds","text":"Acknowledgment
This article is heavily inspired by various tutorials from the polish TheModders forums.
Worlds, saved as .ZEN
files in ZenGin, are archives that contain the world mesh (model), BSP tree, materials and the information of all objects in the world. These objects are called VOBs (\"virtual objects\"). ZEN files can be saved in two ways; compiled and uncompiled. The compiled version is a full-fledged level with a terrain model. Uncompiled ZENs only save the VOB tree and are meant for specific use-cases. Worlds, saved as .ZEN
files in ZenGin, are archives that contain the world mesh (model), BSP tree, materials and the information of all objects in the world. These objects are called VOBs (\"virtual objects\"). ZEN files can be saved in two ways; compiled and uncompiled. The compiled version is a full-fledged level with a terrain model. Uncompiled ZENs only save the VOB tree and are meant for specific use-cases.
Spacer is used to create these .ZEN
files. There are also other world editors. The way of doing things can vary between these editors, so the specifics will be discussed in separate articles for those tools; at the same time, a lot of knowledge carries over between them. Also have in mind that Spacer is the least comfortable of the editors.
"},{"location":"zengin/worlds/#world-contents","title":"World contents","text":"The content of worlds in Gothic can be roughly separated in the following way:
Base level mesh - terrain and buildings, sometimes also trees. VOBs (zCVob
and subclasses) - all interactive objects, items, foliage, small rocks, huts, furniture, ramps etc. Asides from those elements, there are also many invisible VOBs, such as:
Waypoints (zCVobWaypoint
) - used for NPC navigation. Freepoints (zCVobSpot
) - used mainly for NPC routines and roaming behavior for monsters. Startpoints (zCVobStartpoint
) - used only to spawn the player when starting a new game. Teleporting between levels is handled with scripts and uses freepoints to determine where the player will appear. Sound emitters Music zones oCZoneMusic
- music which plays inside the bounding box of this zone. oCZoneMusicDefault
- default music which plays whenever the player is not inside some oCZoneMusic
. Fog zones (zCZoneZFog
) - areas which add fog, e.g. like in swamp areas where the sky is not visible. The setting to fade out the sky is optional though. PFX - particle effects (fire, smoke, fireflies, falling leaves etc.) Note
This list isn't exhaustive.
World also contains information about all materials used by level mesh and VOBs. They are stored in the form of zCMaterial
instances.
World also contains information about all materials used by level mesh and VOBs. They are stored in the form of zCMaterial
instances.
"},{"location":"zengin/worlds/#creating-a-zen-file","title":"Creating a ZEN file","text":"Before VOBs can be added to a world model, the world needs to be compiled. After importing a 3ds model, the world can be compiled as an outdoor or indoor world and saved as a ZEN.
The submeshes used in ZEN files have triangle count limits (it is also advisable to keep triangle count for each submesh under 50k for performance reasons). To get around this limitation and to parallelize work on various areas, it is possible to join multiple ZEN files together, which is done with special macros.
If you take a look at the original maps for Gothic 2, you can notice that they are in folders, where there's e.g. a file called NEWWORLD.ZEN
and multiple .ZEN
files with \"part\" in their name. The latter are the sub-zens used to create the full level.
However, a possibly more comfortable workflow is to have a single world mesh which is internally separated into multiple submeshes. This way triangle count limits won't be exceeded and the world won't need compiling from parts. As a trade-off, it is likely that it won't be possible for multiple people to work on the ZEN world at the same time.
"},{"location":"zengin/worlds/#lighting","title":"Lighting","text":"There are two light types in the game:
Static lights, which are baked onto the level. They can cast shadows (these only take static VOBs into consideration) and don't leak through walls. These have to be recompiled after making changes, but this process should only take moments. Static lights have the downside of only working in indoor worlds and in rooms which are closed with portals. Dynamic lights are calculated during runtime, which allows them to move and change properties (their color, for example), but has a performance cost. Additionally, they don't look the best and will often leak through walls. It is generally advised to use static lights whenever possible.
"},{"location":"zengin/worlds/#portals","title":"Portals","text":"Portals are special parts of outdoor world meshes which separate interiors from exteriors. This allows the level to have dark areas: otherwise interiors are lit the same way as any outside area. Additionally, portals help with performance (interiors aren't rendered unless the player is nearby). Creation of portals has many caveats and will be discussed in a separate article. Portals are also related to NPC behavior (e.g. setting ownership of a room).
"},{"location":"zengin/worlds/#water","title":"Water","text":"Water is a special surface in the world. It has to be properly modelled, and its material has to be set up correctly. You can read more about it in the dedicated article.
"},{"location":"zengin/worlds/#water_1","title":"Water","text":"Water is a special surface in the world. It has to be properly modelled, and its material has to be set up correctly. You can read more about it in the dedicated article.
"},{"location":"zengin/worlds/#optimisation","title":"Optimisation","text":"The game uses occlusion culling, which means that if an object is covered by another object, it is not rendered and saves performance. This means that the performance in a level can be boosted by a lot by creating city walls and mountains and valleys which separate areas.
Occlusion culling isn't a perfect process, so there's also the option of adding GHOSTOCCLUDERs, which are invisible walls which stop areas behind them from rendering. They are a part of the world mesh and are created by assigning a material called GHOSTOCCLUDER to chosen faces. The color of the material is traditionally purplish-blue or pink, but the material itself is not rendered in-game, so this is only to make them stand apart from the rest of the level during modelling. To get more technical, these occluder walls are used to help the BSP algorithm which runs during world compilation.
As mentioned before, another ways of optimisation are portals and limiting the number of dynamic lights. It is also not advisable to make many VOBs be affected by wind.
"},{"location":"zengin/worlds/spacer/","title":"Spacer","text":""},{"location":"zengin/worlds/spacer/#spacer","title":"Spacer","text":"Spacer is the original world editor used to create maps in Gothic and it's installed by the MDK installer.
A good .ZEN
file to start experimenting with Spacer is Toten Insel. It's a simple level which should load without issues for everyone. The map contains a custom texture, but it can be safely ignored.
"},{"location":"zengin/worlds/spacer/#introduction","title":"Introduction","text":"Upon launching Spacer, multiple windows will appear. They are:
The main viewport (black with text on launch) The vobtree - allows to browse and select the objects already placed in a level The object window - it has 3 tabs: Create, Modify and \"...\". Toolbars - there's two of them and each button has a hover hint. The help window - sometimes when clicking on something, this window will show a description. It's usually empty though. The objectpages window - allows access to specific VOB settings. The contents of this window be changed with buttons on the horizontal toolbar. Other windows dedicated to specific functionalities can also be opened or toggled (Window tab in the viewport or the horizontal toolbar).
When importing a mesh instead of a .ZEN
file, some things will change. In this mode, objectpages has material data, one of the toolbars changes completely and the vobtree window changes into a texture browser.
"},{"location":"zengin/worlds/spacer/#configuration","title":"Configuration","text":"Before doing anything else, you will probably want to change a few settings first. Select Settings: View
in the Settings tab in the main viewport to increase the viewport resolution. After doing that, press Align Toolwindows at Screen
or Align Toolwindows at Spacer
in the Window tab to clean up the window placement. You might still need to move some of the tool windows around after this, as they can overlap.
The most comfortable option we found was to set the resolution to something slightly smaller than the screen resolution (e.g. 1600:900 on a 1920:1080 screen) and then aligning the tool windows to screen.
To help with the control sensitivity issues, change the camera movement speed in the Settings: General
.
"},{"location":"zengin/worlds/spacer/#viewport-controls","title":"Viewport controls","text":"The camera has multiple modes of operation. Some of the controls may sound confusing, but will make sense once you try them.
Default selection mode
Arrows move the camera back and forward and rotate it sideways. A
moves the camera up and Y
lowers it.
PageUp
and PageDown
rotate the camera up and down. End
resets this rotation.
Selecting VOBs is done by simply pointing at them with the mouse and clicking.
First-person selection mode
Toggled by the F3
button.
In this mode, you can point the camera with your mouse, and selection is done by pointing the green reticle at a VOB and clicking LMB
. Arrows now move the camera parallel to itself (including sideways).
PageUp
and PageDown
still rotate the camera up and down, but it's better not to use them because it affects how the arrow movement behaves. End
resets this rotation.
Default VOB movement mode
When a VOB is selected, press M
to enter and exit this mode.
The arrows now move the VOB horizontally. Moving it up and down is done with A
and Y
.
The keys above the arrows now rotate the VOB:
Axis 1: Delete
and PageDown
Axis 2: Insert
and PageUp
Axis 3: Home
and End
First-person VOB movement mode
When a VOB is selected, press T
to enter and exit this mode.
The controls are the same as the default selection mode, but the camera is now placed at the selected VOB and it moves with the camera.
One caveat is that the controls are in the local space of the object. What this basically means is that if you rotated the object in any other way than horizontally, the movement and rotation will now be skewed.
Mixed VOB movement mode
When a VOB is selected, press C
to enter and exit this mode. The VOB is now controlled like in the first-person movement mode, but the camera is not placed at the VOB: in other words, the camera remains in the same place.
General
Holding down Shift
speeds up the camera in all of the modes. The numpad can be used for rotating instead of the buttons above the arrows. Both movement modes can be used from either of the selection modes. Movement modes can be selected from the vertical toolbar. This toolbar also has a \"toggle camera position\" button; this switches between two camera placements, which can be controlled independently.
The objects location can also be entered manually through the object window: open the Internals folder and select trafoOSToWSPos
to input them at the bottom of the window. Don't forget to press \"Apply\". Unfortunately the rotation setting uses an odd format and can't be set manually.
"},{"location":"zengin/worlds/spacer/#basic-usage","title":"Basic usage","text":"This section covers some of the basic things done in the editor.
"},{"location":"zengin/worlds/spacer/#inserting-a-vob","title":"Inserting a VOB","text":" In the Create tab in the Objects window, select the VOB type. Choose zcVob
to add a simple decorative model. Right click anywhere on the viewport Select the insert option (Insert [zcVob]
in this case) A VOB without a mesh will be created in the middle of the screen. Try to not deselect it, but if you do, it can be found in the vobtree under the appropriate folder (zcVob
in this case); it can be identified by a green dot. In the Modify tab in the Object window, select \"visual\". Insert the model name in the text form at the bottom of the window. You can use pc_lob_sleeper3.3ds
for now; this mesh should be present in both Gothic 1 and 2. If you unpacked the meshes while installing the MDK or with GothicVDFS, you can also browse to the file using the file button next to the text form. Make sure to click the Apply button. Do this after making any changes in the Object window or they will be lost. Tip
You can use the VOB Bilder tool to comfortably browse model images and names. An online version is currently available here. The UI on the website is in Polish but it's simple enough to not matter.
To make the VOB have collision in-game, double click on cdDyn
(\"collision detection dynamic\") to set it to true. Sometimes this is unadvised, e.g. with bushes or grass. Tip
When placing pickable items, you can press the \"apply physics on selected VOB\" button in the vertical toolbar to make the item drop on the ground. It can save you a lot of work with placing those items. This won't work with a plain cVob though.
"},{"location":"zengin/worlds/spacer/#common-vob-settings","title":"Common VOB settings","text":"VOB settings vary depending on what the VOB type is. They all have common parameters of the base VOB class though. The full description of a zCVob class can be found here.
"},{"location":"zengin/worlds/spacer/#issues","title":"Issues","text":"Spacer 2 received the last update in 2003 and is a very buggy tool. Here are some known issues.
Framerate dependence
The speed of camera in Spacer depends on the framerate. Depending on the angle of the camera and the level, Spacer can have huge framerate, which will make the camera move too quick.
You can try to limit the framerate of Spacer with external tools, but your mileage may vary. Such tools often only limit rendering using fake Vsync, but the underlying logic of the program can still run too fast.
Using the grid snap function can help when the framerate is high, but again: your mileage may vary.
Random freezes and crashes
Spacer will freeze or crash quite often at seemingly random moments. It is extremely important to save often and back up your work.
One of the common ways the editor can freeze is when rotating the camera vertically when the framerate is very high. In that case, changing the camera mode to F3 and back can sometimes help.
Copying VOBs
When copy-pasting a VOB in Spacer (right click menu), the new VOB might be created as a child of the original one and moving one of them will move both. This doesn't seem to be consistent, but it's worth checking before you accidentally ruin the careful placement of the original VOB.
"},{"location":"zengin/worlds/spacer/#troubleshooting","title":"Troubleshooting","text":"You can have issues with loading a ZEN or a world model for a multitude of reasons. Here is some of the known ones.
Some terrain models aren't set up or exported properly. Maps which use custom assets will cause issues or won't even load unless these assets are included in appropriate directories. The severity of this is different depending on the asset type. For example, textures will be replaced with a placeholder, but animations will cause crashes. Note
This section is not exhaustive.
"},{"location":"zengin/worlds/spacer/#creating-zens","title":"Creating ZENs","text":"Presented here are the ways of working with new terrain models.
"},{"location":"zengin/worlds/spacer/#compiling-a-world-mesh","title":"Compiling a world mesh","text":"To create a completely new ZEN, you will first need a level mesh. These can be made from scratch or downloaded, but be aware that meshes, which aren't properly prepared won't compile correctly (you won't be able to move in the viewport). As with any other mesh in Gothic, it has to be in the 3ds format. It is recommended to place the mesh file somewhere in the _work/Data/Meshes
(can be your own subfolder).
You can find free terrain models here if you want to practice this. Note that not all of them might compile properly; this one should be fine though.
First, load the mesh from the File tab of the viewport. To compile the mesh, press Compile World
in the World tab. From here, multiple options are available:
Indoor/Outdoor: determines if the world will have a sky and the way that lighting behaves. Detect leaks: might be related to checking if indoor (\"underground\") worlds have holes in them. In some games such holes can cause performance issues, perhaps it's the same here. Doesn't hurt to enable it. Quick compile: self-explanatory, but the exact effects of this are unknown. Polycheck: presumably checks if the model doesn't exceed triangle limits. Editormode:
On: Spacer will load the mesh in editor mode, which allows you to change materials assigned to triangles and other mesh operations. It is more comfortable to do these things in an external 3D editor, but sometimes using this is recommended, e.g. for setting up portals. You can save the model as a .3ds
in this mode.
Off: Spacer will create a ZEN where you can normally place VOBs. You can now save the world as a compiled ZEN and add VOBs to it.
"},{"location":"zengin/worlds/spacer/#compiling-a-world-from-multiple-meshes","title":"Compiling a world from multiple meshes","text":"First and foremost, the models used for this must be properly positioned and separated in your 3D editor of choice. Then each section must be exported as separate .3ds
files. After that, compile each model and save it as a compiled ZEN. Place them in their own folder. You can place VOBs in those ZEN files, the VOB trees will be merged too.
Now, to join these zens together, you will need to define a macro in Tools>Macros
. These are pretty much identical except for the ZEN list; for example, the Mining Colony ZEN in Gothic 2 (OLDWORLD.ZEN
) is comprised of two models, and the macro looks like this:
reset\nset error 3\nLoad world oldworld\\SURFACE.ZEN\nLoad world oldworld\\OLDCAMP.ZEN\ncompile world outdoor\ncompile light high\n
Then you double-click the macro name to run it and wait. The macro contains the reset directive, but it's worth doing it on a freshly opened Spacer instance just to be safe.
Keep in mind that compiling a world from multiple ZENs is meant as a final step in level production. This is because doing it will cause issues with culling and stop interiors from rendering (and thus stop you from editing it). Instead, the part ZENs are filled with VOBs separately and the world is compiled as a final step before testing the map.
"},{"location":"zengin/worlds/spacer/#updating-world-meshes-in-a-compiled-zen","title":"Updating world meshes in a compiled ZEN","text":"Ideally, updating the world mesh would be avoided, but it's an inevitable need when iterating a map design. Doing this in the original Spacer might not be impossible, but it is generally avoided and Spacer.NET or other editors are used for this instead.
"},{"location":"zengin/worlds/Classes/zCMaterial/","title":"zCMaterial","text":""},{"location":"zengin/worlds/Classes/zCMaterial/#zcmaterial","title":"zCMaterial","text":"Quick Infos
Class Name: zCMaterial
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
zCMaterial
class describes the properties of the game materials.
Danger
zCMaterial
objects are only saved in binary .ZEN
files.
"},{"location":"zengin/worlds/Classes/zCMaterial/#class-members","title":"Class members","text":"Gothic 1Gothic 2 zCMaterial Internals name = \"\" matGroup = UNDEF color = 255 255 255 255 smoothAngle = 60 texture = \"\" texScale = 512 512 texAniFPS = 0 texAniMapMode = NONE texAniMapDir = 0 0 noCollDet = FALSE noLightmap = FALSE lodDontCollapse = FALSE detailObject = \"\" zCMaterial Internals defaultMapping = 2.34375 2.34375 name = \"\" matGroup = UNDEF color = 255 255 255 255 smoothAngle = 60 texture = \"\" texScale = 512 512 texAniFPS = 0 texAniMapMode = NONE texAniMapDir = 0 0 noCollDet = FALSE noLightmap = FALSE lodDontCollapse = FALSE detailObject = \"\" detailObjectScale = 1 forceOccluder = FALSE environmentalMapping = FALSE environmentalMappingStrength = 1 waveMode = NONE waveSpeed = FALSE waveMaxAmplitude = 30 waveGridSize = 100 ignoreSunLight = FALSE alphaFunc = NONE "},{"location":"zengin/worlds/Classes/zCMaterial/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCMaterial/#defaultmapping","title":"defaultMapping
","text":"Default material mapping.
"},{"location":"zengin/worlds/Classes/zCMaterial/#name","title":"name
","text":"Material name. In most cases corresponds to the name of the texture map.
"},{"location":"zengin/worlds/Classes/zCMaterial/#matgroup","title":"matGroup
","text":"Sound accompaniment of the material. Must be specified to produce the correct sounds when moving across the specified material.
Accepted values:
UNDEF
- Undefined. METAL
- Metal. STONE
- Stone. WOOD
- Wood. EARTH
- Earth. WATER
- Water. SNOW
- Snow. "},{"location":"zengin/worlds/Classes/zCMaterial/#color","title":"color
","text":"Texture replacement color in RGBA format. Polygon is in this color until engine applies the texture.
"},{"location":"zengin/worlds/Classes/zCMaterial/#smoothangle","title":"smoothAngle
","text":"Defines the angle of material smoothing between two faces.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texture","title":"texture
","text":"Defines the name of the texture file used for the material, which also determines whether the texture is animated or static.
To create animated textures, add a suffix to the file name _A0
, e.g., NW_Fire_A0.TGA
, NW_Fire_A1.TGA
etc. The texture NW_Fire_A0.TGA
is the first frame. The game engine will automatically search your hard drive for remaining animation files.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texscale","title":"texScale
","text":"Defines the scaling along the X and Y axes. Assigns the necessary texture coordinates to polygons.
"},{"location":"zengin/worlds/Classes/zCMaterial/#texanifps","title":"texAniFPS
","text":"Defines the FPS (frames per seconds) of texture animation, but only if the texture is animated (NAME_A0.*
).
"},{"location":"zengin/worlds/Classes/zCMaterial/#texanimapmode","title":"texAniMapMode
","text":"Texture animation mode.
Accepted values:
NONE
- No texture animation. LINEAR
- Linear texture animation. "},{"location":"zengin/worlds/Classes/zCMaterial/#texanimapdir","title":"texAniMapDir
","text":"Defines the direction and movement speed of animated textures. The values should be significantly lower than 1 (For example 0.00005).
Danger
The animation movement is only enabled when texAniMapMode
is set to LINEAR
mode.
"},{"location":"zengin/worlds/Classes/zCMaterial/#nocolldet","title":"noCollDet
","text":"Defines if collision detection is disabled.
Accepted values:
TRUE
- Collisions disabled. FALSE
- Collisions enabled. "},{"location":"zengin/worlds/Classes/zCMaterial/#nolightmap","title":"noLightmap
","text":"Defines if light map is disabled.
Accepted values:
TRUE
- Disable baking of light maps on the material. FALSE
- Enable baking of light maps on the material. "},{"location":"zengin/worlds/Classes/zCMaterial/#loddontcollapse","title":"lodDontCollapse
","text":"If you activate this option, the texture will not degrade when the camera moves away.
Accepted values:
TRUE
- Disable texture degradation. FALSE
- Enable texture degradation. Note
To prevent the texture from being distorted, you can cancel the creation of a MipMap. It is advisable to use for small objects.
"},{"location":"zengin/worlds/Classes/zCMaterial/#detailobject","title":"detailObject
","text":"An option that allows you to complement the material with an additional texture.
"},{"location":"zengin/worlds/Classes/zCMaterial/#detailobjectscale","title":"detailObjectScale
","text":"Tiling of the overlay image selected in the detailObject
property.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#forceoccluder","title":"forceOccluder
","text":"No information provided.
Accepted values:
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#environmentalmapping","title":"environmentalMapping
","text":"Environment mapping mode. Creates glare on the texture.
Accepted values:
TRUE
- Enable reflection mode. FALSE
- Disable reflection mode. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#environmentalmappingstrength","title":"environmentalMappingStrength
","text":"The strength of environmental reflection on a model.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavemode","title":"waveMode
","text":"Enable wave simulation mode. For example, AMBIENT_GROUND
is used for water textures.
Accepted values:
NONE
- Wave simulation is disabled. AMBIENT_GROUND
- Wave simulation is enabled. GROUND
- No information. AMBIENT_WALL
- No information. WALL
- No information. ENV
- No information. AMBIENT_WIND
- No information. WIND
- No information. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavespeed","title":"waveSpeed
","text":"Wave speed.
Accepted values:
SLOW
- Slow. NORMAL
- Normal. FAST
- Fast. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavemaxamplitude","title":"waveMaxAmplitude
","text":"Maximum wave amplitude.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#wavegridsize","title":"waveGridSize
","text":"Wave mesh size.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#ignoresunlight","title":"ignoreSunLight
","text":"Defines if the material ignores sunlight (doesn't cast shadows).
Accepted values:
TRUE
- Ignore. FALSE
- Don't ignore. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCMaterial/#alphafunc","title":"alphaFunc
","text":"Alpha channel blending function.
Accepted values:
NONE
- None. MAT_DEFAULT
- Use texture alpha channel. BLEND
- Mixing. SUB
- Subtraction. MUL
- Multiplication. MUL2
- Multiplication 2. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/","title":"zCVob","text":""},{"location":"zengin/worlds/Classes/zCVob/#zcvob","title":"zCVob","text":"Quick Infos
Class Name: zCVob
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents so-called virtual objects which appear in the game world. zCVob
is the base class for all virtual objects which include everything from static models like boxes to interactive elements like doors and chests and invisible trigger objects.
"},{"location":"zengin/worlds/Classes/zCVob/#class-members","title":"Class members","text":"Properties of a zCVob class are split into two parts. The Internals are hardly ever needed to be edited manually, they are changed by e.g. moving an object in Spacer. On the other hand the Vob properties can only be changed by the Objects context menu in Spacer.
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE visual = NULL ai = NULL zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE visualAniMode = NONE visualAniModeStrength = 0.0 vobFarClipZScale = 1.0 cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE zbias = 1 isAmbient = FALSE visual = NULL ai = NULL zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE visual = NULL ai = NULL sleepMode = 0 nextOnTimer = 0.0 zCVob Internals pack = 0 presetName = \"\" bbox3DWS = 0 0 0 0 0 0 trafoOSToWSRot = 0 trafoOSToWSPOS = 0 0 200 Vob vobName = \"\" visual = \"\" showVisual = TRUE visualCamAlign = NONE visualAniMode = NONE visualAniModeStrength = 0.0 vobFarClipZScale = 1.0 cdStatic = FALSE cdDyn = FALSE staticVob = FALSE dynShadow = DS_NONE zbias = 1 isAmbient = FALSE visual = NULL ai = NULL sleepMode = 0 nextOnTimer = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/#pack","title":"pack
","text":"Internal property which indicates how the data associated with this virtual object is stored.
"},{"location":"zengin/worlds/Classes/zCVob/#presetname","title":"presetName
","text":"The name of the template that was used to create this virtual object.
"},{"location":"zengin/worlds/Classes/zCVob/#bbox3dws","title":"bbox3DWS
","text":"The 3-dimensional bounding box of this virtual object. Defined by two opposite diagonal points (1x, 1y, 1z
, 2x, 2y, 2z
). This is used in conjunction with cdStatic and cdDyn calculate collisions and interactions with other game objects (NPCs, items, etc.).
Interaction processing begins when object volumes intersect. For example, when the player enters the world change trigger area, the engine loads another game level based on the parameters this trigger. All this happens when the main character's BoundingBox intersects with the trigger's BoundingBox.
The BoundingBox can only be changed using the Edit the Bbox
button in Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/#trafoostowsrot","title":"trafoOSToWSRot
","text":"The rotation of this virtual object in world space, represented by a 3x3 rotation matrix.
"},{"location":"zengin/worlds/Classes/zCVob/#trafoostowspos","title":"trafoOSToWSPos
","text":"Coordinates of the object in world space relative to the center.
Note
This refers to the center of coordinates of the .3DS
file of the game world on which the ZEN
file is built.
The coordinates are set automatically the first time an instance of the class is inserted into the game world. You can change them either directly by entering numerical values in the corresponding fields of the parameter, by moving the vob in spacer.
"},{"location":"zengin/worlds/Classes/zCVob/#vobname","title":"vobName
","text":"An identifier of a zCVob shown in the editor and sometimes used in scripts. The name can be left blank.
For some object classes, entering a name is required: zCVobSpot, zCVobWaypoint, zCTrigger etc.
Danger
Setting a name for every static and insignificant object can lead to an error when parsing the game world.
"},{"location":"zengin/worlds/Classes/zCVob/#visual","title":"visual
","text":"The name of the visual component associated with this object, usually a name of a file.
Following formats are supported:
*.3DS
- Static objects *.PFX
- Particle effects *.TGA
- Textures *.MDS
, *.ASC
- Interactive objects *.MMS
- Animated objects "},{"location":"zengin/worlds/Classes/zCVob/#showvisual","title":"showVisual
","text":"Indicates whether this object should display its visual.
Accepted values:
TRUE
- Display. FALSE
- Do not display. "},{"location":"zengin/worlds/Classes/zCVob/#visualcamalign","title":"visualCamAlign
","text":"Option to align objects relative to the camera.
Accepted values:
NONE
- Not used. YAW
- The object always faces the player. FULL
- The object is aligned relative to the world axes. Note
This may be used with grass or flowers which only consist of a 2-dimensional sprite to have it always face the camera.
"},{"location":"zengin/worlds/Classes/zCVob/#visualanimode","title":"visualAniMode
","text":"Wind simulation option. Used in conjunction with the visualAniModeStrength parameter.
Accepted values:
NONE
- Not used. WIND
- Strong wind effect. Acceptable for herbs. WIND2
- Light wind effect. Acceptable for trees. Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#visualanimodestrength","title":"visualAniModeStrength
","text":"Wind power animation multiplier. Small values such as 0.001
are typically used. Used in conjunction with the visualAniMode parameter.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#vobfarclipzscale","title":"vobFarClipZScale
","text":"Sets the loading range of the VOB object. Depends on the VOB drawing distance specified using the zCZoneVobFarPlane
object.
The range of values is from 0.0
to 2.0
.
With a value of 0.0
, the object is not visible, but collisions are calculated. With a value of 2.0
, the zCVob
drawing range is the same as the draw distance specified in zCZoneVobFarPlane
object.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#cdstatic","title":"cdStatic
","text":"Determines if the virtual object will collide with the static objects (world mesh and other VOBs with cdStatic on).
Accepted values:
TRUE
- Collide with static objects. FALSE
- Don't collide static objects. Tip
A situation often arises when objects \u201crefuse\u201d to move beyond a certain point on the surface. This happens when cdStatic is set to TRUE
, i.e. the object cannot cross the surface another static object. In this case, it is enough to disable the cdStatic parameter for the duration of the move, and turn it on again after the move.
"},{"location":"zengin/worlds/Classes/zCVob/#cddyn","title":"cdDyn
","text":"Determines if the virtual object will collide with dynamic objects (NPCs, items, etc.). This basically determines if the object has collision during gameplay.
Accepted values:
TRUE
- Collide with dynamic objects. FALSE
- Don't collide with dynamic objects. "},{"location":"zengin/worlds/Classes/zCVob/#staticvob","title":"staticVob
","text":"Determines if the VOB is taken into consideration in static lighting calculations in Indoor spaces. Usually enabled in decorative Vobs, but some of the interactive ones have it disabled.
Accepted values:
TRUE
- Calculate the shadow of the object. FALSE
- Do not calculate the shadow of the object. Note
The shadow is calculated when compiling light in Low, Middle or High mode.
"},{"location":"zengin/worlds/Classes/zCVob/#dynshadow","title":"dynShadow
","text":"Indicates whether the object will cast a shadow when affected by dynamic light (e.g. torches).
Accepted values:
DS_NONE
- No shadow. DS_BLOB
- Casts a circular shadow. "},{"location":"zengin/worlds/Classes/zCVob/#zbias","title":"zbias
","text":"The depth-bias for this virtual object.
Can be used remove texture flickering if a .TGA
file is used as rendering.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#isambient","title":"isAmbient
","text":"Indicates that this virtual object is ambient. It looks like this setting was a system used during development when access to the game's source code was available. Basically, the global variable zCWorld::s_bAmbientVobsEnabled
could be used to hide or show virtual objects which have the isAmbient
flag set. In release builds, this variable is always set to true, thus the isAmbient
flag does not have any perceivable effect on the game. It follows, that this field should be ignored by most implementations.
Warning
This option is only available in Gothic II (Spacer2).
"},{"location":"zengin/worlds/Classes/zCVob/#sleepmode","title":"sleepMode
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/#nextontimer","title":"nextOnTimer
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/","title":"zCCSCamera","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#zccscamera","title":"zCCSCamera","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCCSCamera
Version Identifiers: \u2014 Gothic I: 30720
\u2014 Gothic II: 33793
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL zCVob zCCSCamera camTrjFOR = WORLD targetTrjFOR = WORLD loopMode = NONE splLerpMode = PATH ignoreFORVobRotCam = FALSE ignoreFORVobRotTarget = FALSE adaptToSurroundings = FALSE easeToFirstKey = FALSE easeFromLastKey = FALSE totalTime = 10.0 autoCamFocusVobName = \"\" autoCamPlayerMovable = TRUE autoCamUntriggerOnLastKey = TRUE autoCamUntriggerOnLastKeyDelay = 0.0 numPos = 0 numTargets = 0 zCCamTrj_KeyFrame ...1 = NULL zCCamTrj_KeyFrame ...2 = NULL paused = FALSE started = FALSE gotoTimeMode = FALSE csTime = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#camtrjfor","title":"camTrjFOR
","text":"The coordinate system of the key frames of the camera trajectory.
Accepted values:
WORLD
\u2014 Positions are relative to the global world coordinate system. OBJECT
\u2014 Positions are relative to the position of the camera object in the previous frame. Essentially, when the camera travels along the keyframes each subsequent keyframe's position is relative to the position of the previous keyframe. The position of the first keyframe is relative to the initial position of the camera. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#targettrjfor","title":"targetTrjFOR
","text":"The keyframe coordinate system of the target camera trajectory.
Accepted values:
WORLD
\u2014 Positions are relative to the global world coordinate system. OBJECT
\u2014 Positions are relative to the position of the camera object in the previous frame. Essentially, when the camera travels along the keyframes each subsequent keyframe's position is relative to the position of the previous keyframe. The position of the first keyframe is relative to the initial position of the camera. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#loopmode","title":"loopMode
","text":"The repetition mode of the camera animation.
Accepted values:
NONE
\u2014 The camera animation stops after the last frame is reached. RESTART
\u2014 The camera animation starts from the beginning after the last frame is reached. The ModKit states, that this is only useful if the animation is to be interrupted by scripts or triggers. PINGPONG
\u2014 The camera animation re-plays the keyframes in reverse order after reaching the last frame. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#spllerpmode","title":"splLerpMode
","text":"Adjust camera orientation while moving.
Accepted values:
UNDEF
\u2014 Unset. PATH
\u2014 The camera's orientation is specified by the slope of the target path spline. PATH_IGNOREROLL
\u2014 The camera's orientation is similar to PATH
with the only difference being that the camera's XZ plane is always parallel to the world's XZ plane. PATH_ROT_SAMPLES
\u2014 The camera's orientation is based on the keyframes. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#ignoreforvobrotcam","title":"ignoreFORVobRotCam
","text":"Determines whether the orientation to reference VOB objects should be taken into account when passing through key frames.
Accepted values:
TRUE
\u2014 Orientation to VOB reference objects is ignored. This can be useful if VOB objects appear that are calculated by the rotation animation. After this, the orientation is taken into account only once at the beginning of the movement. FALSE
\u2014 Orientation is not ignored. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#ignoreforvobrottarget","title":"ignoreFORVobRotTarget
","text":"Determines the need to take into account the orientation of target key frames to reference VOB objects.
Accepted values:
TRUE
\u2014 Orientation to VOB reference objects is ignored. Orientation to VOB reference objects is ignored. May be necessary when rotation of reference VOBs defines animation. After this, the orientation is taken into account only once at the beginning of the movement. FALSE
\u2014 Orientation is not ignored. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#adapttosurroundings","title":"adaptToSurroundings
","text":"Indicates the need for dynamic adaptation to the environment.
Accepted values:
TRUE
\u2014 Enable adaptation. FALSE
\u2014 Disable adaptation. The camera will not adapt to its environment. Useful in cases where the keyframes in the world have taken an absolute position (i.e. the camTrjFOR parameter is set to WORLD
). "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#easetofirstkey","title":"easeToFirstKey
","text":"Gives a smooth transition of camera position from the first keyframe to the last, if possible.
Accepted values:
TRUE
\u2014 Smooth transition if possible. FALSE
\u2014 No smooth transition. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#easefromlastkey","title":"easeFromLastKey
","text":"Gives a smooth transition of camera position from the last keyframe to the first, if possible.
Accepted values:
TRUE
\u2014 Smooth transition if possible. FALSE
\u2014 No smooth transition. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#totaltime","title":"totalTime
","text":"The duration of the camera animation in seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamfocusvobname","title":"autoCamFocusVobName
","text":"The name of the VOB object which the camera will automatically focus.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamplayermovable","title":"autoCamPlayerMovable
","text":"Indicates whether the player will be able to move when moving the camera animation.
Accepted values:
TRUE
\u2014 The player will be able to move. FALSE
\u2014 The player is motionless. "},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamuntriggeronlastkey","title":"autoCamUntriggerOnLastKey
","text":"Emit an OnUntrigger
event after reaching the last animation frame.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#autocamuntriggeronlastkeydelay","title":"autoCamUntriggerOnLastKeyDelay
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#numpos","title":"numPos
","text":"The number of position key frames for the camera animation.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#numtargets","title":"numTargets
","text":"The number of target key frames for the camera animation.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#paused","title":"paused
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#started","title":"started
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#gototimemode","title":"gotoTimeMode
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCCSCamera/#cstime","title":"csTime
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
A list of position key frames. The number of items is indicated by the numPos
property.\u00a0\u21a9\u21a9\u21a9\u21a9
A list of target key frames. The number of items is indicated by the numTargets
property.\u00a0\u21a9\u21a9\u21a9\u21a9
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/","title":"zCCamTrj_KeyFrame","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#zccamtrj_keyframe","title":"zCCamTrj_KeyFrame","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCCamTrj_KeyFrame
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 zCVob zCCamTrj_KeyFrame time = -1.0 angleRollDeg = 0.0 camFOVScale = 0.0 motionType = SMOOTH motionTypeFOV = SMOOTH motionTypeRoll = SMOOTH motionTypeTimeScale = SMOOTH Details tension = 0.0 bias = 0.0 continuity = 0.0 timeScale = 1.0 timeIsFixed = FALSE originalPose = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#time","title":"time
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#anglerolldeg","title":"angleRollDeg
","text":"The camera rotation angle of the frame along the Z axis.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#camfovscale","title":"camFOVScale
","text":"Focal zoom of the camera's field of view (FOV) of the frame. Use reasonable values to avoid dizzying effects.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontype","title":"motionType
","text":"The type of camera movement for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontypefov","title":"motionTypeFOV
","text":"The type of focus change for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontyperoll","title":"motionTypeRoll
","text":"The type of rotation for the frame.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#motiontypetimescale","title":"motionTypeTimeScale
","text":"Unclear.
Accepted values:
SMOOTH
\u2014 The movement method is calculated taking into account nearby frames. LINEAR
\u2014 Constant speed in the current frame. STEP
- Step by step. Movement is jerky. SLOW
- The camera movement slows down in the current frame. FAST
- The camera movement accelerates in the current frame. CUSTOM
- Not implemented. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#tension","title":"tension
","text":"Defines the bend of the camera motion curve at the specified key. Larger values result in a sharper bend.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#bias","title":"bias
","text":"Determines the slope of a line in one direction. The direction of the slope is determined by the sign, and the steepness by the value.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#continuity","title":"continuity
","text":"Determines the amount of curve discontinuity at this animation key.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#timescale","title":"timeScale
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#timeisfixed","title":"timeIsFixed
","text":"An auxiliary flag indicating the time of the key frame, which cannot be changed automatically.
Accepted values:
TRUE
\u2014 The time of this frame is set manually and cannot be changed automatically. FALSE
\u2014 The frame time is calculated from the total specified animation playback time. "},{"location":"zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/#originalpose","title":"originalPose
","text":"Unknown.
Warning
This property is not available in the Spacer.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/","title":"zCVobLevelCompo","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/#zcvoblevelcompo","title":"zCVobLevelCompo","text":"Quick Infos
Class Name: zCVobLevelCompo
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Used as root objects of game levels. Only used to group together other VObjects. Only one of the zCVobLevelCompo
objects will have a visual which corresponds to the mesh of the world it exists in. Generally, it can be ignored and has no relevance to other VObjects in the hierarchy.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLevelCompo/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/","title":"zCVobLight","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#zcvoblight","title":"zCVobLight","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: zCVobLight
Version Identifiers: \u2014 Gothic I: 46080
\u2014 Gothic II: 39168
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents a virtual light source which lights up nearby game objects. Point and spot light sources are supported and may be animated with different colors and ranges.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE canMove = FALSE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE zCVob zCVobLight VobLight lightPresetInUse = \"\" lightType = POINT range = 0 color = 255 255 255 255 spotConeAngle = 0 lightStatic = TRUE lightQuality = HIGH lensflareFX = \"\" Dynamic Light turnedOn = TRUE rangeAniScale = \"\" rangeAniFPS = 0 rangeAniSmooth = TRUE colorAniList = \"\" colorAniFPS = 0 colorAniSmooth = TRUE canMove = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightpresetinuse","title":"lightPresetInUse
","text":"The name of the selected light template. Templates can be found in _work/data/Presets/LightPresets.zen
. This property is irrelevant for most use-cases.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lighttype","title":"lightType
","text":"The type of the light source.
Accepted values:
POINT
\u2014 A point light source. SPOT
\u2014 A spot light source. "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#range","title":"range
","text":"The range in which this light source illuminates objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#color","title":"color
","text":"The color of this light source in RGBA form.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#spotconeangle","title":"spotConeAngle
","text":"The angle of the beam cone for spotlights. Only relevant if lightType
is SPOT
, ignored otherwise.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightstatic","title":"lightStatic
","text":"Determines whether this is a static light or not. Static lights are baked into the world when its lighting is compiled. This makes static lights faster at runtime, but it also means, that they cannot change in any way after the world is compiled.
Accepted values:
TRUE
\u2014 This light is a static light. FALSE
\u2014 This light is a dynamic light. "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lightquality","title":"lightQuality
","text":"Determines the quality of the light source. What exactly changes with these values is unknown.
Accepted values:
HIGH
\u2014 Highest quality. MEDIUM
\u2014 Medium quality. LOW_FASTEST
\u2014 Low quality (used for almost all lights). "},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#lensflarefx","title":"lensflareFX
","text":"The name of the lensflare effect associated with this light. Empty if there is no associated lensflare effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#turnedon","title":"turnedOn
","text":"Whether this dynamic light is turned on.
Accepted values:
TRUE
\u2014 The light is turned on. FALSE
\u2014 The light is turned off. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeaniscale","title":"rangeAniScale
","text":"Frames for the light's range animation. Its value is a space-separated list of floats where each float is one key frame of the animation. A value of 1.0
corresponds to the initial range
of the light source, a value of 2.0
corresponds to double the initial range
and a value of 0.5
means half the initial range
. The range animation is further controlled by rangeAniFPS
and rangeAniSmooth
.
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeanifps","title":"rangeAniFPS
","text":"The speed of the range animation in frames per second. The animation frames are defined in rangeAniScale
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#rangeanismooth","title":"rangeAniSmooth
","text":"Whether the range animation should smoothly interpolate between keyframes.
Accepted values:
TRUE
\u2014 Turn on interpolation. FALSE
\u2014 Turn off interpolation. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranilist","title":"colorAniList
","text":"Frames for the light's color animation. Its value is a space-separated list of colors where each element can either be an RGB color consisting of three integers enclosed by parentheses or a greyscale color consisting of a single integer. For example: (255 0 0) 100 (255 50 180)
would result in #ff0000 #646464, #ff32b4. The color animation is further controlled by colorAniFPS
and colorAniSmooth
.
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranifps","title":"colorAniFPS
","text":"The speed of the color animation in frames per second. The animation frames are defined in colorAniList
Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#coloranismooth","title":"colorAniSmooth
","text":"Whether the color animation should smoothly interpolate between keyframes.
Accepted values:
TRUE
\u2014 Turn on interpolation. FALSE
\u2014 Turn off interpolation. Warning
This value is only valid for dynamic lights. Check lightStatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobLight/#canmove","title":"canMove
","text":"Unknown.
Warning
This value is only valid for dynamic lights in Gothic II. Check lightstatic
before use.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/","title":"zCVobSpot","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/#zcvobspot","title":"zCVobSpot","text":"Quick Infos
Class Name: zCVobSpot
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Spot objects are used to mark a position and orientation in virtual space. They are equivalent in function to way net free points and can be used in scripts to spawn other objects at their location.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobSpot/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/","title":"zCVobStair","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/#zcvobstair","title":"zCVobStair","text":"Quick Infos
Class Name: zCVobStair
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: Unused Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Used to mark staircase models in Gothic I only. This type of VObject was taken into account by the NPC pathfinding routines to properly ascend and descend staircases.
Warning
This VObject is only available in Gothic I.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStair/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) Unavailable.
Unavailable.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/","title":"zCVobStartpoint","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/#zcvobstartpoint","title":"zCVobStartpoint","text":"Quick Infos
Class Name: zCVobStartpoint
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Marks the players initial position when loading in the game level. Behaves like zCVobSpot
but causes the game to put the player at its location and in its orientation when the world is loaded.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobStartpoint/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/","title":"zCVobWaypoint","text":""},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/#zcvobwaypoint","title":"zCVobWaypoint","text":"Quick Infos
Class Name: zCVobWaypoint
Version Identifiers: \u2014 Gothic I: Unknown \u2014 Gothic II: Unknown Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
Waypoints are used to mark a position and orientation in virtual space like zCVobSpot
, but are combined into a path network through which NPCs will perform pathfinding. Waypoints can be used in scripts to spawn other objects at their location.
Warning
zCVobWaypoint
objects aren't saved in .ZEN
files. Their zCWaypoint
representations are used instead.
"},{"location":"zengin/worlds/Classes/zCVob/zCVobWaypoint/#class-members","title":"Class members","text":"Gothic 1Gothic 2 "},{"location":"zengin/worlds/Classes/zCVob/oCVob/","title":"oCVob","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/#ocvob","title":"oCVob","text":"Quick Infos
Class Name: oCVob
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: Unused Sources: \u2014 zk.gothickit.dev
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/","title":"oCItem","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#ocitem","title":"oCItem","text":"Quick Infos
Class Name: oCItem
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents an item in the game world. Items are special VObjects which are tied to a script instance which defines their attributes. They have physics enabled and can be targeted and picked up by the player.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCItem itemInstance = \"\" amount = 0 flags = 0 zCVob oCVob oCItem itemInstance = \"\" amount = 0 flags = 0 "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#iteminstance","title":"itemInstance
","text":"The name of the script instance representing the item.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#amount","title":"amount
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCItem/#flags","title":"flags
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/","title":"oCMOB","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#ocmob","title":"oCMOB","text":"Quick Infos
Class Name: oCMOB
Version Identifiers: \u2014 Gothic I: 47105
\u2014 Gothic II: 47105
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which can optionally be moved and/or carried.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" zCVob oCVob oCMOB MOB focusName = \"\" hitpoints = 0 damage = 0 moveable = FALSE takeable = FALSE focusOverride = FALSE soundMaterial = WOOD visualDestroyed = \"\" owner = \"\" ownerGuild = \"\" isDestroyed = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#focusname","title":"focusName
","text":"The name of the object as seen in-game when focusing it.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#hitpoints","title":"hitpoints
","text":"The number of hitpoints of the object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#damage","title":"damage
","text":"The damage dealt by the object when being used.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#moveable","title":"moveable
","text":"Whether the object can be moved by the player.
Accepted values:
TRUE
\u2014 The object can be moved FALSE
\u2014 The object can not be moved "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#takeable","title":"takeable
","text":"Whether the object can be carried by the player.
Accepted values:
TRUE
\u2014 The object can be carried FALSE
\u2014 The object can not be carried "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#focusoverride","title":"focusOverride
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#soundmaterial","title":"soundMaterial
","text":"The sound to play when the object is hit.
Accepted values:
WOOD
\u2014 Wood. STONE
\u2014 Stone. METAL
\u2014 Metal. LEATHER
\u2014 Leather. CLAY
\u2014 Clay. GLAS
\u2014 Glass. "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#visualdestroyed","title":"visualDestroyed
","text":"The name of the visual to use when the object is destroyed. Behaves like zCVob.visual.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#owner","title":"owner
","text":"The name of the script instance of the NPC who is the owner of this object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#ownerguild","title":"ownerGuild
","text":"The name of the guild this object belongs to. This name corresponds to the script constant for each guild (i.e. GIL_BAU
), found in Constants.d
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/#isdestroyed","title":"isDestroyed
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/","title":"oCMobInter","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#ocmobinter","title":"oCMobInter","text":"Quick Infos
Class Name: oCMobInter
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Interactive objects can be interacted with by NPCs and the player. Every time the object is interacted with, an OnTrigger
event is sent to the triggerTarget
object.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE zCVob oCVob oCMOB oCMobInter stateNum = 0 triggerTarget = \"\" useWithItem = \"\" conditionFunc = \"\" onStateFunc = \"\" rewind = FALSE "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#statenum","title":"stateNum
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#triggertarget","title":"triggerTarget
","text":"The name of the VObject(s) to send an OnTrigger
event to when this object is interacted with. Controlled by the rewind
property.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#usewithitem","title":"useWithItem
","text":"The name of the item which the player or NPC must have in their inventory in order to interact with the object. Corresponds to the name of the item instance in the scripts.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#conditionfunc","title":"conditionFunc
","text":"The name of a script function which, when called, determines whether the object can be interacted with. The script function returns an int which is either 0
, if the object should be disabled and 1
if it should be enabled.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#onstatefunc","title":"onStateFunc
","text":"The name of a script function to be called when the object is being used.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/#rewind","title":"rewind
","text":"Determines whether an OnTrigger
event should be sent every time the object is interacted with or only the first time.
Accepted values:
TRUE
\u2014 Send OnTrigger
events multiple times FALSE
\u2014 Only send the event once "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/","title":"oCMobBed","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/#ocmobbed","title":"oCMobBed","text":"Quick Infos
Type: Virtual Object Format Name: ZenGin Archive File Extension: .ZEN
Class Name: oCMobBed
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
VObject marking beds for NPCs and the player to sleep on. In the original Gothic I, there is a bug which prevents oCMobBed
s from working correctly, so it is recommended to instead use oCMobDoor
and attach the visual of a bed when targeting that platform.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed zCVob oCVob oCMOB oCMobInter oCMobBed "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/","title":"oCMobFire","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#ocmobfire","title":"oCMobFire","text":"Quick Infos
Class Name: oCMobFire
Version Identifiers: \u2014 Gothic I: 18433
\u2014 Gothic II: 18433
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
An object with an integrated fire effect. Only supports rigged models as visuals.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" zCVob oCVob oCMOB oCMobInter oCMobFire fireSlot = \"\" fireVobtreeName = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#fireslot","title":"fireSlot
","text":"The bone of the rigged model to place the fire effect at.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/#firevobtreename","title":"fireVobtreeName
","text":"The name of the template file which contains the configuration of the fire effect. For example: FIRETREE_MEDIUM.ZEN
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/","title":"oCMobLadder","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/#ocmobladder","title":"oCMobLadder","text":"Quick Infos
Class Name: oCMobLadder
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject representing a ladder. NPCs can interact with ladders by climbing.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder zCVob oCVob oCMOB oCMobInter oCMobLadder "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/","title":"oCMobSwitch","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/#ocmobswitch","title":"oCMobSwitch","text":"Quick Infos
Class Name: oCMobSwitch
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A VObject representing a switch with two states.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch zCVob oCVob oCMOB oCMobInter oCMobSwitch "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/","title":"oCMobWheel","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/#ocmobwheel","title":"oCMobWheel","text":"Quick Infos
Class Name: oCMobWheel
Version Identifiers: \u2014 Gothic I: 35585
\u2014 Gothic II: 35585
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A wheel with four different states. For example, this is used for the gates of the old camp in Gothic I.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel zCVob oCVob oCMOB oCMobInter oCMobWheel "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/","title":"oCMobLockable","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#ocmoblockable","title":"oCMobLockable","text":"Quick Infos
Class Name: oCMobLockable
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many lockable objects like containers and doors.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" zCVob oCVob oCMOB oCMobInter oCMobContainer Lockable locked = FALSE keyInstance = \"\" pickLockStr = \"\" "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#locked","title":"locked
","text":"Determines whether the container is locked.
Accepted values:
TRUE
\u2014 The container is locked FALSE
\u2014 The container is not locked "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#keyinstance","title":"keyInstance
","text":"The name of the item script instance which unlocks the container.
Tip
Only relevant if the container is locked.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/#picklockstr","title":"pickLockStr
","text":"The combination which unlocks this container when picking the lock. Each character of the string is either R
or L
where R
stands for \"Right\" and L
stands for \"Left\". If empty, the lock can not be picked. Example: LRRLLRL
.
Tip
Only relevant if the container is locked.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/","title":"oCMobContainer","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#ocmobcontainer","title":"oCMobContainer","text":"Quick Infos
Class Name: oCMobContainer
Version Identifiers: \u2014 Gothic I: 64513
\u2014 Gothic II: 64513
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
An object which contains items.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer Container NumOfEntries = 0 oCItem ... = NULL zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobContainer Container NumOfEntries = 0 oCItem ... = NULL "},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#contains","title":"contains
","text":"The items found inside the container as a comma-separated list. Each element of the list starts with the name of the item script instance and is optionally followed by a colon and a number, indicating the number of that item to be found inside. Example: ItMi_Gold:75, ItFo_Fish:2, ItMi_Quartz
.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/#numofentries","title":"NumOfEntries
","text":"The number of items in the container.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/","title":"oCMobDoor","text":""},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/#ocmobdoor","title":"oCMobDoor","text":"Quick Infos
Class Name: oCMobDoor
Version Identifiers: \u2014 Gothic I: 64513
\u2014 Gothic II: 64513
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject representing a door. This is also used for NPCs navigating the waynet.
"},{"location":"zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor zCVob oCVob oCMOB oCMobInter oCMobLockable oCMobDoor "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/","title":"zCEffect","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/#zceffect","title":"zCEffect","text":"Quick Infos
Class Name: zCEffect
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many visual and sound effects.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/","title":"zCEarthquake","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#zcearthquake","title":"zCEarthquake","text":"Quick Infos
Class Name: zCEarthquake
Version Identifiers: \u2014 Gothic I: Unused \u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to create an earthquake effect when it receives an OnTrigger
event. An earthquake is represented by a shaking camera.
Warning
This VObject is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) Unavailable
zCVob zCEffect zCEarthquake Earthquake radius = 200 timeSec = 5 amplitudeCM = 0 Unavailable
zCVob zCEffect zCEarthquake Earthquake radius = 200 timeSec = 5 amplitudeCM = 0 "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#radius","title":"radius
","text":"The radius of the earthquake effect
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#timesec","title":"timeSec
","text":"The duration of the earthquake effect in seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/#amplitudecm","title":"amplitudeCM
","text":"The amplitude of the earthquake effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/","title":"zCPFXController","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#zcpfxcontroller","title":"zCPFXController","text":"Quick Infos
Class Name: zCPFXControler
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A particle system in virtual space. Its effect can be activated and deactivated using the OnTrigger
and OnUntrigger
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE zCVob zCEffect zCPFXController pfxName = \"\" killVobWhenDone = TRUE pfxStartOn = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#pfxname","title":"pfxName
","text":"The name of the particle effect. Corresponds to a .ZEN
file containing the particle system definition.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#killvobwhendone","title":"killVobWhenDone
","text":"Disable the particle effect after it runs once.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/#pfxstarton","title":"pfxStartOn
","text":"Whether to start the particle effect when the level is loaded.
Accepted values:
TRUE
\u2014 Start the particle effect when loading the world. FALSE
\u2014 Don't start the particle effect automatically. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/","title":"zCVobAnimate","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#zcvobanimate","title":"zCVobAnimate","text":"Quick Infos
Class Name: zCVobAnimate
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to create animated models. The visual of such objects can either be a morph mesh or a model with a skeletal animation (i.e. a model script). The animation of these objects can be started and stopped using OnTrigger
and OnUntrigger
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobAnimate zCVob zCEffect zCVobAnimate zCVob zCEffect zCVobAnimate startOn = \"\" isRunning = FALSE zCVob zCEffect zCVobAnimate startOn = \"\" isRunning = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#starton","title":"startOn
","text":"Whether to start this animation when loading the level.
Accepted values:
TRUE
\u2014 Immediately start the animation when the level is loaded. FALSE
\u2014 Don't automatically start the animation. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/#isrunning","title":"isRunning
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/","title":"zCVobLensFlare","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#zcvoblensflare","title":"zCVobLensFlare","text":"Quick Infos
Class Name: zCVobLensFlare
Version Identifiers: \u2014 Gothic I: 64704
\u2014 Gothic II: 193
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Represents a lens flare effect. Behaves exactly like the base zCVob
but has a lens flare effect.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare zCVob zCEffect zCVobLensFlare "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/#lensflarefx","title":"lensflareFX
","text":"The name of the lens flare effect. Must be one of the effects listed in /_work/data/Presets/Lensflare.zen
.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/","title":"zCVobScreenFX","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/#zcvobscreenfx","title":"zCVobScreenFX","text":"Quick Infos
Class Name: zCVobScreenFX
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Screen effect VObjects are used to create special effects. They are used for field-of-view changes, adding black bars for a cinematic feel to the game and other post-processing effects.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX zCVob zCEffect zCVobScreenFX "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/","title":"zCTouchAnimate","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#zctouchanimate","title":"zCTouchAnimate","text":"Quick Infos
Class Name: zCTouchAnimate
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 20483
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
A VObject that plays its animation when it receives an OnTick
event (basically when something touches it).
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate zCVob zCEffect zCTouchAnimate "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/#presentation","title":"Presentation","text":"Following video shows the behaviour of this VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/","title":"zCTouchAnimateSound","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#zctouchanimatesound","title":"zCTouchAnimateSound","text":"Quick Infos
Class Name: zCTouchAnimateSound
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 20483
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
Object similar to zCTouchAnimate
, but allowing to specify a sound that plays on the event activation.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound zCVob zCEffect zCTouchAnimate zCTouchAnimateSound "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#sfxtouch","title":"sfxTouch
","text":"The name of the sound produced upon contact with an object.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/#presentation","title":"Presentation","text":"Following video shows the behaviour of this VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/","title":"zCTouchDamage","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#zctouchdamage","title":"zCTouchDamage","text":"Quick Infos
Class Name: zCTouchDamage
Version Identifiers: \u2014 Gothic I: 36865
\u2014 Gothic II: 36865
Source: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which damages other VObjects colliding with it.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX zCVob zCEffect zCTouchDamage TouchDamage damage = 0 DamageType Barrier = TRUE Blunt = FALSE Edge = FALSE Fire = FALSE Fly = FALSE Magic = FALSE Point = FALSE Fall = FALSE damageRepeatDelaySec = 0 damageVolDownScale = 0 damageCollType = BOX "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damage","title":"damage
","text":"The amount of damage being dealt.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#barrier","title":"Barrier
","text":"Accepted values:
TRUE
\u2014 Deal barrier damage FALSE
\u2014 Do not deal barrier damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#blunt","title":"Blunt
","text":"Accepted values:
TRUE
\u2014 Deal blunt damage (blunt weapons) FALSE
\u2014 Do not deal blunt damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#edge","title":"Edge
","text":"Accepted values:
TRUE
\u2014 Deal edge damage (sharp weapons) FALSE
\u2014 Do not deal edge damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fire","title":"Fire
","text":"Accepted values:
TRUE
\u2014 Deal fire damage FALSE
\u2014 Do not deal fire damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fly","title":"Fly
","text":"Accepted values:
TRUE
\u2014 Deal knockout damage FALSE
\u2014 Do not deal knockout damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#magic","title":"Magic
","text":"Accepted values:
TRUE
\u2014 Deal magic damage FALSE
\u2014 Do not deal magic damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#point","title":"Point
","text":"Accepted values:
TRUE
\u2014 Deal point damage (bows and crossbows) FALSE
\u2014 Do not deal point damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#fall","title":"Fall
","text":"Accepted values:
TRUE
\u2014 Deal fall damage FALSE
\u2014 Do not deal fall damage "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagerepeatdelaysec","title":"damageRepeatDelaySec
","text":"The delay between damage ticks when applying continuous damage. If set to 0
, only deals the damage once per collision. If set to a value greater than 0
, deals damage every damageRepeatDelaySec
seconds.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagevoldownscale","title":"damageVolDownScale
","text":"A scale value used in conjunction with damageCollType
. Its function depends on the type of collision detection used.
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/#damagecolltype","title":"damageCollType
","text":"The type of collision detection to use for damage calculations.
Accepted values:
NONE
\u2014 Disable collision detection and thus damage application. BOX
\u2014 Scale the bbox3dws
of the zCTouchDamage
object by damageVolDownScale
and use this new bounding box to calculate collisions with other VObjects POINT
\u2014 Scale the bbox3dws
of the colliding object by damageVolDownScale
and only deal damage if it contains the center point of the zCTouchDamage
object. If the visual
of the zCTouchDamage
object is a particle effect, test against every particle instead. "},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/","title":"oCTouchDamage","text":""},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/#octouchdamage","title":"oCTouchDamage","text":"Quick Infos
Class Name: oCTouchDamage
Version Identifiers: \u2014 Gothic I: 36865
\u2014 Gothic II: 36865
Sources: \u2014 zk.gothickit.dev
"},{"location":"zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage zCVob zCEffect zCTouchDamage oCTouchDamage "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/","title":"zCTriggerBase","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#zctriggerbase","title":"zCTriggerBase","text":"Quick Infos
Class Name: zCTriggerBase
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for many triggers.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/#triggertarget","title":"triggerTarget
","text":"The name of VObject to send OnTrigger
and OnUntrigger
events to after processing.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/","title":"zCCodeMaster","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#zccodemaster","title":"zCCodeMaster","text":"Quick Infos
Class Name: zCCodeMaster
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Source: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
zCCodeMaster
VObjects keep a list of 'slave' VObjects and keep track of events received by them. If the master receives an OnTrigger
event from a slave, it remembers that it did. After it has receives an OnTrigger
message from all slaves, it emits an OnTrigger
event to the triggerTarget
. Receiving or sending an OnTrigger
event is also referred to as an 'activation' for this purpose.
Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" zCVob zCTriggerBase zCCodeMaster CodeMaster orderRelevant = FALSE OrderRelevant firstFalseIsFailure = TRUE triggerTargetFailure = \"\" OrderNotRelevant slaveVobName ... = \"\" numSlavesTriggered = 0 slaveTriggered ... = NULL "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#orderrelevant","title":"orderRelevant
","text":"Controls whether the master should keep track of the order it receives messages from its slaves.
Accepted values:
TRUE
\u2014 Only send an OnTrigger
event to the triggerTarget
if the slaves have fired in the exact order they are configured here. Also counts multiple activations. FALSE
\u2014 Send an OnTrigger
event to the triggerTarget
after all slaves have fired at least once, regardless of order. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#firstfalseisfailure","title":"firstFalseIsFailure
","text":"Controls when the slave activation sequence is considered to be incorrect. After the sequence is marked as incorrect an OnTrigger
event is sent to triggerTargetFailure
.
Accepted values:
TRUE
\u2014 The sequence is considered to be incorrect as soon as one slave is activated out-of-order. FALSE
\u2014 The sequence is considered to be incorrect only after all slaves have been activated at least once and they were activated out-of-order. Warning
Only relevant if orderRelevant
is set to TRUE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#triggertargetfailure","title":"triggerTargetFailure
","text":"The name of the VObject to emit an OnTrigger
event to if the activation sequence fails. This is controlled by firstFalseIsFailure
.
Warning
Only relevant if orderRelevant
is set to TRUE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#untriggercancels","title":"untriggerCancels
","text":"Controls whether slaves can emit OnUntrigger
events to the master VObject to mark themselves as deactivated.
Accepted values:
TRUE
\u2014 When the master receives an OnUntrigger
event from the slave, it marks it as not having been activated. FALSE
\u2014 The master ignore OnUntrigger
events from its slaves. Warning
Only relevant if orderRelevant
is set to FALSE
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#slavevobname","title":"slaveVobName
","text":"The name of a slave VObject.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/#numslavestriggered","title":"numSlavesTriggered
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/","title":"zCMessageFilter","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#zcmessagefilter","title":"zCMessageFilter","text":"Quick Infos
Class Name: zCMessageFilter
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
Transforms any incoming OnTrigger
and OnUntrigger
events before passing them on to the trigger target. All OnTrigger
and OnUntrigger
messages received by this zCMessageFilter
VObject are transformed according to onTrigger
and onUntrigger
and then passed on to the VObject with the name specified in the triggerTarget
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER zCVob zCTriggerBase zCMessageFilter onTrigger = MT_TRIGGER onUntrigger = MT_UNTRIGGER "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#ontrigger","title":"onTrigger
","text":"The type of event to emit to the triggerTarget
if this VObject receives an OnTrigger
message.
Accepted values:
MT_NONE
\u2014 Don't emit another event. MT_TRIGGER
\u2014 Emit an OnTrigger
event. MT_UNTRIGGER
\u2014 Emit an OnUntrigger
event. MT_ENABLE
\u2014 Emit an Enable
event. MT_DISABLE
\u2014 Emit a Disable
event. MT_TOGGLE_ENABLED
\u2014 Emit a ToggleEnabled
event. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/#onuntrigger","title":"onUntrigger
","text":"The type of event to emit to the triggerTarget
if this VObject receives an OnUntrigger
message.
Accepted values:
MT_NONE
\u2014 Don't emit another event. MT_TRIGGER
\u2014 Emit an OnTrigger
event. MT_UNTRIGGER
\u2014 Emit an OnUntrigger
event. MT_ENABLE
\u2014 Emit an Enable
event. MT_DISABLE
\u2014 Emit a Disable
event. MT_TOGGLE_ENABLED
\u2014 Emit a ToggleEnabled
event. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/","title":"zCMoverControler","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#zcmovercontroler","title":"zCMoverControler","text":"Quick Infos
Class Name: zCMoverControler
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject used to control zCMover
objects of type NSTATE_SINGLE_KEYS
specifically. zCMoverControler
objects react to incoming OnTrigger
events to send a pre-configured event to the target mover object named by the triggerTarget
propery, controlling its animation. Mover controllers can make movers go to a specific keyframe in their animation or just step one keyframe back and forth at a time.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 zCVob zCTriggerBase zCMoverControler moverMessage = GOTO_KEY_FIXED_DIRECTLY gotoFixedKey = 0 "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#movermessage","title":"moverMessage
","text":"The type of event to emit to the triggerTarget
when this controller receives an OnTrigger
event.
Accepted values:
GOTO_KEY_FIXED_DIRECTLY
\u2014 Make the target mover directly go to the keyframe specified in gotoFixedKey
, skipping all intermediate keyframes. GOTO_KEY_FIXED_ORDER
\u2014 Make the target mover go to the keyframe specified in in gotoFixedKey
while still going through all intermediate keyframes. GOTO_KEY_NEXT
\u2014 Make the target mover go to the next keyframe in sequence. Wraps around to the first keyframe. GOTO_KEY_PREV
\u2014 Make the target mover go to the previous keyframe in sequence. Wraps around to the last keyframe. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/#gotofixedkey","title":"gotoFixedKey
","text":"The keyframe of the mover referred to by triggerTarget
to move to.
Warning
Only relevant if moverMessage
is GOTO_KEY_FIXED_DIRECTLY
or GOTO_KEY_FIXED_ORDER
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/","title":"zCTriggerUntouch","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/#zctriggeruntouch","title":"zCTriggerUntouch","text":"Quick Infos
Class Name: zCTriggerUntouch
Version Identifiers: \u2014 Gothic I: 52224
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A trigger which fires an OnTrigger
event to its triggerTarget
if any OnUntouch
event is emitted from an inanimate object within the object's bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch zCVob zCTriggerBase zCTriggerUntouch "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/","title":"zCTriggerWorldStart","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#zctriggerworldstart","title":"zCTriggerWorldStart","text":"Quick Infos
Class Name: zCTriggerWorldStart
Version Identifiers: \u2014 Gothic I: 52224
\u2014 Gothic II: 52224
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special trigger which fires an OnTrigger
event to its triggerTarget
when the world is loaded and started.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE zCVob zCTriggerBase zCTriggerWorldStart fireOnlyFirstTime = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/#fireonlyfirsttime","title":"fireOnlyFirstTime
","text":"Determines whether to fire the OnTrigger
event only the first time the world is loaded.
Accepted values:
TRUE
\u2014 Only fire the event if this is the first time the world is loaded. FALSE
\u2014 Fire the event every time the world is loaded. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/","title":"zCTrigger","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#zctrigger","title":"zCTrigger","text":"Quick Infos
Class Name: zCTrigger
Version Identifiers: \u2014 Gothic I: 47105
\u2014 Gothic II: 47105
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
VObject to process and relay specific filtered events. When a zCTrigger
receives an OnTrigger
, OnDamage
, or OnTouch
event it checks whether the event source (an oCNpc
, the player or another VObject) should be acknowledged (see respondToNPC
, respondToPC
and respondToObject
respectively). It then verifies if it should react to the specific event by checking the reactToOnTrigger
, reactToOnDamage
and reactToOnTouch
properties. If both checks succeed, an OnTrigger
event is sent to the triggerTarget
and the trigger is considered to be activated. zCTrigger
objects can be enabled and disabled by firing OnEnable
, OnDisable
and OnToggleEnabled
events at them.
Tip
The respondTo{Object,PC,NPC,VobName}
properties are logically linked by and \"or\" expression.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE nextTimeTriggerable = 0.0 savedOtherVob = NULL countCanBeActivated zCVob zCTriggerBase zCTrigger Trigger ActivationFilter reactToOnTrigger = TRUE reactToOnTouch = TRUE reactToOnDamage = TRUE respondToObject = TRUE respondToPC = TRUE respondToNPC = TRUE startEnabled = TRUE respondToVobName = \"\" numCanBeActivated = -1 retriggerWaitSec = 0 damageThreshold = 0 FireBehavior fireDelaySec = 0 sendUntrigger = TRUE nextTimeTriggerable = 0.0 savedOtherVob = NULL countCanBeActivated = 0 isEnabled = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoontrigger","title":"reactToOnTrigger
","text":"Whether this trigger should react to OnTrigger
events.
Accepted values:
TRUE
\u2014 Do react to OnTrigger
events by sending an OnTrigger
message to the triggerTarget
If sendUntrigger
is set to TRUE
, also sends an OnUntrigger
event to the triggerTarget
if the trigger receives an OnUntrigger
event. FALSE
\u2014 Ignore OnTrigger
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoontouch","title":"reactToOnTouch
","text":"Whether this trigger should react to OnTouch
events.
Accepted values:
TRUE
\u2014 Do react to OnTouch
events by sending an OnTrigger
message to the triggerTarget
If sendUntrigger
is set to TRUE
, also sends an OnUntrigger
event to the triggerTarget
if the trigger receives an OnUntouch
event. FALSE
\u2014 Ignore OnTouch
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#reacttoondamage","title":"reactToOnDamage
","text":"Whether this trigger should react to OnDamage
events.
Accepted values:
TRUE
\u2014 Do react to OnDamage
events by sending an OnTrigger
message to the triggerTarget
FALSE
\u2014 Ignore OnDamage
events. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtoobject","title":"respondToObject
","text":"Whether this trigger should process events coming from inanimate objects.
Accepted values:
TRUE
\u2014 Do process events from inanimate objects. FALSE
\u2014 Ignore events from inanimate objects. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtopc","title":"respondToPC
","text":"Whether this trigger should process events coming from the player.
Accepted values:
TRUE
\u2014 Do process events from the player. FALSE
\u2014 Ignore events from the player. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtonpc","title":"respondToNPC
","text":"Whether this trigger should process events coming from NPCs.
Accepted values:
TRUE
\u2014 Do process events from NPCs. FALSE
\u2014 Ignore events from NPCs. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#startenabled","title":"startEnabled
","text":"Determines whether the trigger is initially enabled. Enabled triggers will process incoming events and send outgoing events while disabled triggers do not. Triggers can be activated and deactivated at runtime by sending them OnEnable
, OnDisable
or OnToggleEnabled
events.
Accepted values:
TRUE
\u2014 Enable the trigger when the world is loaded. FALSE
\u2014 Do not enable the trigger when the world is loaded. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#respondtovobname","title":"respondToVobName
","text":"Whether this trigger should process events coming from VObjects with this name. If empty, match no VObject name directly.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#numcanbeactivated","title":"numCanBeActivated
","text":"The number of times the trigger will process incoming events. If set to -1
the trigger will process an infinite number of events.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#retriggerwaitsec","title":"retriggerWaitSec
","text":"The number of seconds that have to elapse after processing an event before the trigger will process additional events. All events received by the trigger during that time are ignored.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#damagethreshold","title":"damageThreshold
","text":"The amount of damage which must be dealt for the trigger to react to an OnDamage
event.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#firedelaysec","title":"fireDelaySec
","text":"The number of seconds to wait before emitting the OnTrigger
event after processing.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#senduntrigger","title":"sendUntrigger
","text":"Whether to send and OnUntrigger
event to the triggerTarget
after the trigger receives an OnUntrigger
or OnUntouch
event. Only fires the OnUntrigger
event if reactToOnTrigger
and reactToOnTouch
are set to TRUE
respectively.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#nexttimetriggerable","title":"nextTimeTriggerable
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#savedothervob","title":"savedOtherVob
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#countcanbeactivated","title":"countCanBeActivated
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/#isenabled","title":"isEnabled
","text":"Unknown.
Warning
This property is only available in saved games made using Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/","title":"oCCSTrigger","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/#occstrigger","title":"oCCSTrigger","text":"Quick Infos
Class Name: oCCSTrigger
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A special trigger VObject which can start a cutscene. The triggerTarget
must be the name of the cutscene (without the extension) to be started. For this to work, the cutscene must already be loaded. OnUntrigger
events are ignored by oCCSTrigger
s.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger zCVob zCTriggerBase zCTrigger oCCSTrigger "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/","title":"oCTriggerChangeLevel","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#octriggerchangelevel","title":"oCTriggerChangeLevel","text":"Quick Infos
Class Name: oCTriggerChangeLevel
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special zCTrigger
which in addition to performing all other trigger actions also causes the engine to load another level when activated.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" zCVob zCTriggerBase zCTrigger oCTriggerChangeLevel levelName = \"\" startVobName = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#levelname","title":"levelName
","text":"The name of the level to load including the file extension.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/#startvobname","title":"startVobName
","text":"The name of the VObject in the new level to place the player at.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/","title":"oCTriggerScript","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#octriggerscript","title":"oCTriggerScript","text":"Quick Infos
Class Name: oCTriggerScript
Version Identifiers: \u2014 Gothic I: 24577
\u2014 Gothic II: 24577
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
A special zCTrigger
which in addition to performing all other trigger actions also calls a script function when the trigger is activated. OnUntrigger
events do not result in the script function being called.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript zCVob zCTriggerBase zCTrigger oCTriggerScript "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/#scriptfunc","title":"scriptFunc
","text":"The name script function to call when the trigger successfully processes a message.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/","title":"zCMover","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#zcmover","title":"zCMover","text":"Quick Infos
Class Name: zCMover
Version Identifiers: \u2014 Gothic I: 39936
\u2014 Gothic II: 39936
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which can move along a pre-determined path in response to an event. Movers can be controlled through a set of keyframes or the animation of their visuals. If the visual has an attached animation to be used as the mover's animation, it must have the following animations which are run depending on the mover's state: S_OPEN
, S_CLOSED
, T_CLOSED_2_OPEN
, T_OPEN_2_CLOSED
, S_LOCKED
, S_UNLOCKED
, T_UNLOCKED_TO_LOCKED
, T_LOCKED_TO_UNLOCKED
.
Each mover is in one of three states, \"open\", \"closed\" or \"moving\". Keyframe 0
(or S_OPEN
when using the visual's animation) corresponds to the \"open\" state while the last keyframe (or S_CLOSED
) corresponds to the \"closed\" state. When transitioning between the \"open\" and \"closed\" states, the mover is in the \"moving\" state during which it sequentially moves between its keyframes (or runs the T_CLOSED_2_OPEN
or T_OPEN_TO_CLOSED
animations). Movers with their moverBehavior
set to NSTATE_SINGLE_KEYS
are an exception to this rule: each keyframe can individually be addressed as a state.
Movers are specialized triggers. Before beginning their animation, movers first filter the incoming events as per the zCTrigger
's rules and only start the animation if the event passes through the filters. When the mover reaches the \"open\" state after being activated, it emits an OnTrigger
event according to the fire behavior set for the zCTrigger
. Similarly, when it reaches the \"closed\" state it emits an OnUntrigger
event.
Movers can be enabled and disabled using the OnEnable
, OnDisable
and OnToggleDisabled
events.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE autoRotate = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST actKeyPosDelta = 0 0 0 actKeyframeF = 0.0 actKeyframe = 0 nextKeyframe = 0 moveSpeedUnit = 0.0 advanceDir = 0.0 moverState = ? numTriggerEvents = 0 stayOpenTimeDest = 0.0 Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" zCVob zCTriggerBase zCTrigger zCMover Mover moverBehavior = 2STATE_TOGGLE touchBlockerDamage = 0.0 stayOpenTimeSec = 0.0 moverLocked = FALSE autoLinkEnabled = FALSE autoRotate = FALSE Keyframe numKeyframes = 0 moveSpeed = 0.0 posLerpType = CURVE speedType = CONST actKeyPosDelta = 0 0 0 actKeyframeF = 0.0 actKeyframe = 0 nextKeyframe = 0 moveSpeedUnit = 0.0 advanceDir = 0.0 moverState = ? numTriggerEvents = 0 stayOpenTimeDest = 0.0 Sound sfxOpenStart = \"\" sfxOpenEnd = \"\" sfxMoving = \"\" sfxCloseStart = \"\" sfxCloseEnd = \"\" sfxLock = \"\" sfxUnlock = \"\" sfxUseLocked = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverbehavior","title":"moverBehavior
","text":"Controls how the mover behaves in response to events (\"activation\").
Accepted values:
2STATE_TOGGLE
\u2014 Receiving either event causes the state of the mover to swap. The direction of the animation is reversed. 2STATE_TRIGGER_CTRL
\u2014 An OnTrigger
causes the mover to transition to the \"open\" state while an OnUntrigger
event causes the mover to transition to the \"closed\" state. 2STATE_OPEN_TIMED
\u2014 An OnTrigger
event causes the mover to transition to the \"open\" state. It than transitions to the \"closed\" state after a fixed amount of time specified by stayOpenTimeSec
. NSTATE_LOOP
\u2014 The mover opens and closes in a loop indefinitely. NSTATE_SINGLE_KEYS
\u2014 The mover can transition to each keyframe separately. Often used in conjunction with a zCMoverControler
. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#touchblockerdamage","title":"touchBlockerDamage
","text":"The amount of damage to deal to objects in the way of the mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#stayopentimesec","title":"stayOpenTimeSec
","text":"The number of seconds a mover with the 2STATE_OPEN_TIMED
behavior stays in the \"open\" state until transitioning to the \"closed\" state again.
Warning
Only relevant if moverBehavior
is 2STATE_OPEN_TIMED
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverlocked","title":"moverLocked
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#autolinkenabled","title":"autoLinkEnabled
","text":"Determines whether the position of the object triggering the mover should be tied to the mover's position.
Accepted values:
TRUE
\u2014 When the mover transitions, the position of the triggering object follows the position of the mover. FALSE
\u2014 The triggering object's position is uncoupled from the position of the mover. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#autorotate","title":"autoRotate
","text":"Whether to automatically rotate the mover along its movement trajectory. For example, this is used for making fish always face in the direction they're moving.
Accepted values:
TRUE
\u2014 Automatically face the mover forward along its trajectory. FALSE
\u2014 Never automatically rotate the mover. Warning
Only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#numkeyframes","title":"numKeyframes
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#movespeed","title":"moveSpeed
","text":"The movement speed for transitioning between keyframes in units per millisecond.
Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#poslerptype","title":"posLerpType
","text":"Defines how the mover should interpolate between the keyframe positions. Only affects the mover's position, never its rotation.
Accepted values:
CURVE
\u2014 Smoothly transition between keyframes. LINEAR
\u2014 Linearly transition between keyframes. Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#speedtype","title":"speedType
","text":"Controls the acceleration and deceleration behavior of the mover.
Accepted values:
CONST
\u2014 Mover with a constant speed. SLOW_START_END
\u2014 Slowly accelerate at the first keyframe and decelerate at the last keyframe. SLOW_START
\u2014 Slowly accelerate at the first keyframe but don't decelerate at the end. SLOW_END
\u2014 Slowly decelerate at the last keyframe but don't accelerate at the start. SEG_SLOW_START_END
\u2014 Slowly accelerate at the beginning of each keyframe and decelerate at the end of each keyframe. SEG_SLOW_START
\u2014 Slowly accelerate at the beginning of each keyframe but don't decelerate at the end. SEG_SLOW_END
\u2014 Slowly decelerate at the end of each keyframe but don't accelerate at the beginning. Warning
Only relevant if manually specified keyframes are used. Ignored when using the visual for the animation.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxopenstart","title":"sfxOpenStart
","text":"The name of the sound to play at the beginning of the opening sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxopenend","title":"sfxOpenEnd
","text":"The name of the sound to play at the end of the opening sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxmoving","title":"sfxMoving
","text":"The name of the sound to play in a loop while the mover is transitioning between keyframes.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxclosestart","title":"sfxCloseStart
","text":"The name of the sound to play at the beginning of the closing sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxcloseend","title":"sfxCloseEnd
","text":"The name of the sound to play at the end of the closing sequence.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxlock","title":"sfxLock
","text":"The name of the sound to play when locking a mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxunlock","title":"sfxUnlock
","text":"The name of the sound to play when unlocking a mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#sfxuselocked","title":"sfxUseLocked
","text":"The name of the sound to play when using a locked mover.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyposdelta","title":"actKeyPosDelta
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyframef","title":"actKeyframeF
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#actkeyframe","title":"actKeyframe
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#nextkeyframe","title":"nextKeyframe
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#movespeedunit","title":"moveSpeedUnit
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#advancedir","title":"advanceDir
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#moverstate","title":"moverState
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#numtriggerevents","title":"numTriggerEvents
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/#stayopentimedest","title":"stayOpenTimeDest
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/","title":"zCTriggerList","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#zctriggerlist","title":"zCTriggerList","text":"Quick Infos
Class Name: zCTriggerList
Version Identifiers: \u2014 Gothic I: 59776
\u2014 Gothic II: 5505
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A special trigger which emits the OnTrigger
events emitted by the zCTrigger
to multiple targets. How the events are sent can be configured through listProcess
. The triggerTarget
and fireDelaySec
properties of zCTrigger
should be ignored.
OnUntrigger
events sent to the trigger list are propagated to all targets in the list.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 actTarget = 0 sendOnTrigger = TRUE zCVob zCTriggerBase zCTrigger zCTriggerList TriggerList listProcess = LP_ALL triggerTarget0 = \"\" fireDelay0 = 0 triggerTarget1 = \"\" fireDelay1 = 0 triggerTarget2 = \"\" fireDelay2 = 0 actTarget = 0 sendOnTrigger = TRUE "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#listprocess","title":"listProcess
","text":"Controls how events are sent to the targets.
Accepted values:
LP_ALL
\u2014 Every target in the trigger list is sent the OnTrigger
event sequentially. The fireDelay
of each target is taken into account so that target n
is fired after sum(fireDelay0, ..., fireDelayN-1)
seconds. LP_NEXT_ONE
\u2014 The event is sent to the next target in the list. LP_RAND_ONE
\u2014 The event is sent to a random target in the list. "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#triggertarget","title":"triggerTarget
","text":"The name of the VObject to send events to. Behaves like triggerTarget
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#firedelay","title":"fireDelay
","text":"The delay after which to fire the event to the target. Behaves like fireDelaySec
.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#acttarget","title":"actTarget
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/#sendontrigger","title":"sendOnTrigger
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/","title":"zCTriggerTeleport","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#zctriggerteleport","title":"zCTriggerTeleport","text":"Quick Infos
Class Name: zCTriggerTeleport
Version Identifiers: \u2014 Gothic I: 59776
\u2014 Gothic II: 45570
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru
This VObject allows teleporting a hero to the waypoint.
Note
To make trigger work, you must set the value of the cdDyn
parameter to True
and specify the Waypoint in triggerTarget
parameter.
"},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport zCVob zCTriggerBase zCTrigger zCTriggerTeleport "},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/#sfxteleport","title":"sfxTeleport
","text":"Sound accompaniment of character teleport.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/","title":"zCZone","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/#zczone","title":"zCZone","text":"Quick Infos
Class Name: zCZone
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 zk.gothickit.dev
The base class for effect zones.
Warning
This object is an abstract base class and cannot be instantiated by itself.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/","title":"oCZoneMusic","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#oczonemusic","title":"oCZoneMusic","text":"Quick Infos
Class Name: oCZoneMusic
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the music to be played within its bounding box. Music zones may overlap; if they do, their priority
property determines which music zone should be used. The camera object is used to test which music zone applies. If no music zone applies the music defined in the optional oCZoneMusicDefault
is used.
The name of the music theme to be played is defined by the vobName
. Notice that end of the name is taken as a C_MUSICTHEME prefix. For example zone OLDCAMP_OC
will play theme starting with OC_
.
Tip
If the suffix _NCI
or _NCO
is added to the end of the zone name, it snows instead of rains in the zone.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE local_enabled = FALSE dayEntranceDone = FALSE nightEntranceDone = FALSE zCVob zCZone oCZoneMusic enabled = TRUE priority = 0 ellipsoid = FALSE reverbLevel = 0 volumeLevel = 100 loop = TRUE local_enabled = FALSE dayEntranceDone = FALSE nightEntranceDone = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#enabled","title":"enabled
","text":"Whether the music zone is enabled when loading the level. When disabled, no music will be played in the zone.
Accepted values:
TRUE
\u2014 Enable the music zone when loading the level FALSE
\u2014 The not enable the zone "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#priority","title":"priority
","text":"The priority of the music zone if two zones overlap. A higher number means a higher priority. 0
is the lowest possible priority.
Warning
Only relevant if two zCZoneMusic
zones overlap.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#ellipsoid","title":"ellipsoid
","text":"Determines the shape of the zone.
Accepted values:
TRUE
\u2014 The zone forms an ellipsoid within the bounding box. FALSE
\u2014 The zone exactly mirrors the bounding box. "},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#reverblevel","title":"reverbLevel
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#volumelevel","title":"volumeLevel
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#loop","title":"loop
","text":"Unclear.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#local_enabled","title":"local_enabled
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#dayentrancedone","title":"dayEntranceDone
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/#nightentrancedone","title":"nightEntranceDone
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/","title":"oCZoneMusicDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/#oczonemusicdefault","title":"oCZoneMusicDefault","text":"Quick Infos
Class Name: oCZoneMusicDefault
Version Identifiers: \u2014 Gothic I: 0
\u2014 Gothic II: 0
Sources: \u2014 spacerhilfedatei.sph \u2014 zk.gothickit.dev
Determines the default music to be played when the camera is outside any oCZoneMusic
zones. The volume-related options of the zone are ignored. There may only be one oCZoneMusicDefault
object in a world.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault zCVob zCZone oCZoneMusic oCZoneMusicDefault "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/","title":"zCVobSound","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#zcvobsound","title":"zCVobSound","text":"Quick Infos
Class Name: zCVobSound
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 12289
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Emits a sound defined by a script instance in a given radius. The sound playback can be activated by sending an OnTrigger
event to the VObject and sending an OnUntrigger
event disables the sound playback.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" soundIsRunning = FALSE soundAllowedToRun = FALSE zCVob zCZone zCVobSound Sound sndVolume = 100 sndMode = LOOPING sndRandDelay = 5 sndRandDelayVar = 2 sndStartOn = TRUE sndAmbient3D = FALSE sndObstruction = FALSE sndConeAngle = 0 sndVolType = SPHERE sndRadius = 1200 sndName = \"\" soundIsRunning = FALSE soundAllowedToRun = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndvolume","title":"sndVolume
","text":"The volume of the sound effect in percent (0-100).
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndmode","title":"sndMode
","text":"Determines how the sound effect is played.
Accepted values:
LOOPING
\u2014 The sound effect is repeated endlessly ONCE
\u2014 The sound plays once RANDOM
\u2014 The sound effect is repeated endlessly with a random delay between repetitions "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndranddelay","title":"sndRandDelay
","text":"The average delay between repetitions in seconds if sndMode
is RANDOM
.
Warning
Only relevant if sndMode
is RANDOM
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndranddelayvar","title":"sndRandDelayVar
","text":"The maximum deviation of the random delay between repetitions if sndMode
is RANDOM
. The resulting delay will be a value between sndRandDelay
\u00b1 sndRandDelayVar
.
Warning
Only relevant if sndMode
is RANDOM
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndstarton","title":"sndStartOn
","text":"Whether to start the sound when loading the world.
Accepted values:
TRUE
\u2014 Start the sound when the world is loaded FALSE
\u2014 Only start the sound in response to an OnTrigger
event "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndambient3d","title":"sndAmbient3D
","text":"Determines whether the sound is an omnidirectional ambient sound. It will change volume depending on the distance to this VObject, but it won't sound as if this VObject is emitting the effect.
Accepted values:
TRUE
\u2014 Emit an ambient sound effect FALSE
\u2014 Emit a directional sound effect "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndobstruction","title":"sndObstruction
","text":"Whether to dampen the sound when there is no direct path from the VObject to the listener.
Accepted values:
TRUE
\u2014 The sound is dampened by obstructions FALSE
\u2014 The sound is not dampened "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndconeangle","title":"sndConeAngle
","text":"When set to a value other than 0
, determines a cone in front of the VObject in which the sound can be heard. To listeners outside of that cone, the sound is not heard. Only values between 0
and 360
are valid.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndvoltype","title":"sndVolType
","text":"Determines the type of volume used to check whether the sound can be heard.
Accepted values:
SV_SPHERE
\u2014 The sound the be heard in a sphere around this VObject. SV_ELLIPSOID
\u2014 The sound can be heard within an ellipsoid defined by the VObject's bounding box. "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndradius","title":"sndRadius
","text":"The radius in which the sound can be heard.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#sndname","title":"sndName
","text":"The name of the script instance describing the sound.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#soundisrunning","title":"soundIsRunning
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/#soundallowedtorun","title":"soundAllowedToRun
","text":"Unknown.
Warning
This property is only available in saved games.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/","title":"zCVobSoundDaytime","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#zcvobsounddaytime","title":"zCVobSoundDaytime","text":"Quick Infos
Class Name: zCVobSoundDaytime
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 12289
Sources: \u2014 spacerhilfedatei.sph \u2014 gothic-library.ru \u2014 zk.gothickit.dev
Emits a sound defined by a script instance in a given radius during a given time during the day. Optionally, another sound can be defined which is played outside the defined time range (example: birds during the day and crickets at night).
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" zCVob zCZone zCVobSound zCVobSoundDaytime SoundDaytime sndStartTime = 0 sndEndTime = 0 sndName2 = \"\" "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndstarttime","title":"sndStartTime
","text":"The time of day after which the sound can be heard (13.5
corresponds to 13:30
). Must be less than sndEndTime
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndendtime","title":"sndEndTime
","text":"The time of day after which the sound can no longer be heard (13.5
corresponds to 13:30
). Must be greater than sndStartTime
.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/#sndname2","title":"sndName2
","text":"The name of the script instance describing the sound to play outside the hours defined by sndStartTime
and sndendtime
. May be empty.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/","title":"zCZoneVobFarPlane","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#zczonevobfarplane","title":"zCZoneVobFarPlane","text":"Quick Infos
Class Name: zCZoneVobFarPlane
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the loading range of VObjects within its bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 zCVob zCZone zCZoneVobFarPlane vobFarPlaneZ = 12000.0 innerRangePerc = 0.0 "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#vobfarplanez","title":"vobFarPlaneZ
","text":"The loading range of VObject within.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/#innerrangeperc","title":"innerRangePerc
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/","title":"zCZoneVobFarPlaneDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/#zczonevobfarplanedefault","title":"zCZoneVobFarPlaneDefault","text":"Quick Infos
Class Name: zCZoneVobFarPlaneDefault
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the default loading range of VObjects in the entire world. There may only be one of these objects in each world. Its effect can be overridden using zCZoneVobFarPlane objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane zCVob zCZone zCZoneVobFarPlane zCZoneVobFarPlane "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/","title":"zCZoneZFog","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#zczonezfog","title":"zCZoneZFog","text":"Quick Infos
Class Name: zCZoneZFog
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which causes fog to appear within its bounding box.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 fadeOutSky = FALSE overrideColor = FALSE zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 zCVob zCZone zCZoneZFog ZoneZFog fogRangeCenter = 0.0 innerRangePerc = 0.0 fogColor = 0 0 0 fadeOutSky = FALSE overrideColor = FALSE "},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#class-member-overview","title":"Class member overview","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fograngecenter","title":"fogRangeCenter
","text":"The maximum distance of visibility if the player is in the center of the fog object.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#innerrangeperc","title":"innerRangePerc
","text":"Unknown.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fogcolor","title":"fogColor
","text":"The color of the fog.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#fadeoutsky","title":"fadeOutSky
","text":"Whether to hide the sky when the player is inside the fog.
Accepted values:
TRUE
\u2014 Do not show the skybox when the player is inside the fog. FALSE
\u2014 Do show the skybox when the player is inside the fog. Warning
This property is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/#overridecolor","title":"overrideColor
","text":"Unclear.
Warning
This property is only available in Gothic II.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/","title":"zCZoneZFogDefault","text":""},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/#zczonezfogdefault","title":"zCZoneZFogDefault","text":"Quick Infos
Class Name: zCZoneZFogDefault
Version Identifiers: \u2014 Gothic I: 12289
\u2014 Gothic II: 52224
Sources: \u2014 gothic-library.ru \u2014 zk.gothickit.dev
A VObject which defines the default fog for the entire world. There may only be one of these objects in each world. Its effect can be overridden using zCZoneZFog objects.
"},{"location":"zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/#class-members","title":"Class members","text":"Gothic 1Gothic 2Gothic 1 (Save)Gothic 2 (Save) zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault zCVob zCZone zCZoneZFog zCZoneZFogDefault "}]}
\ No newline at end of file
diff --git a/sitemap.xml b/sitemap.xml
index 8f7d3a1ad0..c7cc9b45aa 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -1,210 +1,211 @@
- https://gothic-modding-community.github.io/gmc/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/notready/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/preferences/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/contribute/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/genome/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/genome/general_info/object_persistence/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/genome/tools/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/music/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/video/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/anims/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/anims/events/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/anims/mds/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/anims/tutorials/standalone_animation/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/general_info/directory_structure/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/general_info/object_persistence/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/general_info/vdfs/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/meshes/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/meshes/water/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_info/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_item/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_menu/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_menuitem/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_musicsys_cfg/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_musictheme/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_svm/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/afsp/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/afsp/afsp_eim/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/constants/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/examples/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/floats/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/setup/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/arrays/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/asm/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/call/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/debug/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/ini_access/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/jumps_loops/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/keyboard/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/mem_access/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/mem_utility/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/menu_access/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/objects/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/parser/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/string/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/time_benchmark/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/win_utilities/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/setup/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/userconstants/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/anim8/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/bars/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/bloodsplats/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/buffs/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/buttons/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/console_commands/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/cursor/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/dialoggestures/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/focusnames/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/gamestate/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/names/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/render/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/saves/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/trialoge/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/ai_function/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/binary_machines/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/draw3d/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/event_handler/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/frame_functions/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hashtables/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hook_dae/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hook_engine/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/int64/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/interface/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/item_helper/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/list/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/locals/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/misc/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/permmem/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/queue/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/random/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/sprite/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/string_builder/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/talents/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/timer/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/view/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/gameKeyEvents/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/setBarPositions/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/classes/c_trigger/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/classes/helperclasses/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/meta/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/other/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/examples/signposts/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/ai/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/cast/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/events_vars/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/hlp/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/log/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/mdl/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/menu/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/mob/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/npc/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/par/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/string/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/vob/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/wld/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/events/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/extern/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/while/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/doc/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/log/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/mdl/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/sound/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/sound/tutorials/change_sfx/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/textures/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/textures/32bit_texture/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/textures/multitextures/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/gothic_sourcer/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/zSpy/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/daedalus_tools/daedalus_language_server/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/daedalus_tools/decdat/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/libraries/zenkit/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/vdfs_tools/gothic_vdfs/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/tools/vdfs_tools/vdfs_tool/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/patch/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zSplitDialogs/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zbassmusic/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/controls/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_engine_absolute/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_engine_logical/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_gamepad/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/logical_functions/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/sdk/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/sdk/events/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/sdk/externals/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/sdk/getting_started/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/union/sdk/hooks/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/spacer/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCMaterial/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCCSCamera/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobLevelCompo/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobLight/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobSpot/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobStair/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobStartpoint/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobWaypoint/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCItem/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCVobSound/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/ 2024-07-08 daily
- https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/ 2024-07-08 daily
\ No newline at end of file
+ https://gothic-modding-community.github.io/gmc/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/notready/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/preferences/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/contribute/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/genome/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/genome/general_info/object_persistence/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/genome/tools/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/music/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/video/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/anims/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/anims/events/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/anims/mds/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/anims/tutorials/standalone_animation/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/general_info/directory_structure/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/general_info/object_persistence/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/general_info/vdfs/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/meshes/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/meshes/portals/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/meshes/water/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_info/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_item/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_menu/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_menuitem/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_musicsys_cfg/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_musictheme/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/classes/c_svm/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/afsp/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/afsp/afsp_eim/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/constants/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/examples/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/floats/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/setup/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/arrays/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/asm/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/call/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/debug/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/ini_access/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/jumps_loops/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/keyboard/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/mem_access/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/mem_utility/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/menu_access/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/objects/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/parser/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/string/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/time_benchmark/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/ikarus/functions/win_utilities/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/setup/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/userconstants/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/anim8/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/bars/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/bloodsplats/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/buffs/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/buttons/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/console_commands/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/cursor/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/dialoggestures/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/focusnames/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/gamestate/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/names/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/render/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/saves/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/applications/trialoge/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/ai_function/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/binary_machines/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/draw3d/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/event_handler/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/frame_functions/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hashtables/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hook_dae/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/hook_engine/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/int64/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/interface/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/item_helper/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/list/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/locals/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/misc/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/permmem/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/queue/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/random/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/sprite/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/string_builder/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/talents/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/timer/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/lego/tools/view/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/gameKeyEvents/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/standalone/setBarPositions/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/classes/c_trigger/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/classes/helperclasses/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/hooks/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/meta/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/daedalus_injection/other/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/examples/signposts/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/ai/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/cast/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/events_vars/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/hlp/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/log/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/mdl/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/menu/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/mob/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/npc/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/par/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/string/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/vob/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/externals/wld/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/dialogues/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/events/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/extern/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/namespaces/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/extenders/zparserextender/syntax_extensions/while/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/doc/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/log/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/scripts/externals/mdl/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/sound/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/sound/tutorials/change_sfx/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/textures/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/textures/32bit_texture/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/textures/multitextures/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/gothic_sourcer/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/zSpy/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/daedalus_tools/daedalus_language_server/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/daedalus_tools/decdat/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/libraries/zenkit/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/vdfs_tools/gothic_vdfs/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/tools/vdfs_tools/vdfs_tool/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/patch/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zSplitDialogs/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zbassmusic/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/controls/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_engine_absolute/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_engine_logical/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/keys_gamepad/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/plugins/zgamepad/logical_functions/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/sdk/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/sdk/events/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/sdk/externals/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/sdk/getting_started/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/union/sdk/hooks/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/spacer/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCMaterial/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCCSCamera/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCCamTrj_KeyFrame/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobLevelCompo/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobLight/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobSpot/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobStair/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobStartpoint/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCVobWaypoint/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCItem/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobBed/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobFire/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLadder/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobSwitch/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobWheel/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobContainer/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/oCVob/oCMOB/oCMobInter/oCMobLockable/oCMobDoor/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCEarthquake/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCPFXControler/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobAnimate/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobLensFlare/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCVobScreenFX/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchAnimate/zCTouchAnimateSound/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCEffect/zCTouchDamage/oCTouchDamage/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCCodeMaster/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCMessageFilter/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCMoverControler/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerUntouch/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTriggerWorldStart/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCCSTrigger/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerChangeLevel/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/oCTriggerScript/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCMover/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerList/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCTriggerBase/zCTrigger/zCTriggerTeleport/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/oCZoneMusic/oCZoneMusicDefault/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCVobSound/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCVobSound/zCVobSoundDaytime/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneVobFarPlane/zCZoneVobFarPlaneDefault/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/ 2024-07-25 daily
+ https://gothic-modding-community.github.io/gmc/zengin/worlds/Classes/zCVob/zCZone/zCZoneZFog/zCZoneZFogDefault/ 2024-07-25 daily
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index 6526dd0428..ae5a530ef8 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ
diff --git a/zengin/anims/events/index.html b/zengin/anims/events/index.html
index 09b09d5952..302d32f25b 100644
--- a/zengin/anims/events/index.html
+++ b/zengin/anims/events/index.html
@@ -610,6 +610,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/anims/index.html b/zengin/anims/index.html
index 18031b8337..0be38c1a74 100644
--- a/zengin/anims/index.html
+++ b/zengin/anims/index.html
@@ -371,6 +371,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/anims/mds/index.html b/zengin/anims/mds/index.html
index 8fcf80475f..ba5fa67ab4 100644
--- a/zengin/anims/mds/index.html
+++ b/zengin/anims/mds/index.html
@@ -432,6 +432,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/anims/tutorials/standalone_animation/index.html b/zengin/anims/tutorials/standalone_animation/index.html
index 92b82cc283..dcfb8dc6ad 100644
--- a/zengin/anims/tutorials/standalone_animation/index.html
+++ b/zengin/anims/tutorials/standalone_animation/index.html
@@ -404,6 +404,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/general_info/directory_structure/index.html b/zengin/general_info/directory_structure/index.html
index 2c31abeb33..3d440c1cba 100644
--- a/zengin/general_info/directory_structure/index.html
+++ b/zengin/general_info/directory_structure/index.html
@@ -410,6 +410,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/general_info/object_persistence/index.html b/zengin/general_info/object_persistence/index.html
index a6dcb59682..98e23279d6 100644
--- a/zengin/general_info/object_persistence/index.html
+++ b/zengin/general_info/object_persistence/index.html
@@ -446,6 +446,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/general_info/vdfs/index.html b/zengin/general_info/vdfs/index.html
index 9b18311fe2..f69db123b0 100644
--- a/zengin/general_info/vdfs/index.html
+++ b/zengin/general_info/vdfs/index.html
@@ -430,6 +430,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/index.html b/zengin/index.html
index ec9f0c83c9..7e71a848bd 100644
--- a/zengin/index.html
+++ b/zengin/index.html
@@ -371,6 +371,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
diff --git a/zengin/meshes/index.html b/zengin/meshes/index.html
index a9743cec69..a01c09fc63 100644
--- a/zengin/meshes/index.html
+++ b/zengin/meshes/index.html
@@ -6,7 +6,7 @@
-
+
Meshes - Gothic Modding Community
@@ -371,6 +371,15 @@
Meshes
+
+
+
+ Portals
+
+
+
+
+
@@ -2964,23 +2973,23 @@
In 3D graphics, meshes are collections of vertices, edges, and faces that create 3D objects. ZenGin use meshes to create the world model and objects in the world.
Info
-
Not all objects that seem to be a mesh are in the "Meshes" category. Except every animated objects, the animation targets (like beds or doors) also belong to the Animations .
+
Not all objects that seem to be a mesh are in the "Meshes" category. Except every animated objects, the animation targets (like beds or doors) also belong to the Animations .
Raw
ZenGin uses the .3ds
file format for raw source meshes. That is one of the file formats used by the Autodesk 3ds Max , which was used by the Gothic developers.
The .3ds
files can be opened with any 3D modeling software that supports this format. But, to easily import/export them with engine-specific settings, it is recommended to use Blender 2.80+ with the KrxImpExp extension.
3DS limitations
-The 3DS format has some disadvantages when building levels. With very large levels such as SURFACE.3DS
, you reach the upper limit of 65,536 polygons per object that are permitted in a .3ds
file. To get around this problem, proceed as follows: simply “cut” the mesh into several small parts that are below the 64K poly limit. For example, the SURFACE.3DS
was dismantled into 4 parts of roughly equal size and then completely exported. This mesh is then melted together again into an object in the spacer. This happens due to overlapping vertices.
+The 3DS format has some disadvantages when building levels. With very large levels such as SURFACE.3DS
, you reach the upper limit of 65,536 triangles per object that are permitted in a .3ds
file. To get around this problem, proceed as follows: simply “cut” the mesh into several small parts that are below the 64K triangle limit. For example, the SURFACE.3DS
was dismantled into 4 parts of roughly equal size and then completely exported. This meshes are then merged during the world compilation process into single object in the spacer.
Compiled
-Source formats are great for editing, but can be a bit heavy for the engine use (ASCII based formats are slower to parse and work with), because of that ZenGin compiles these meshes into internal compiled formats. In the case of the world it is .MSH
format and in the case of objects in the world it is the .MRM
(multi resolution mesh) with LOD information
+Source formats are great for editing, but can be a bit heavy for the engine use (ASCII based formats are slower to parse and work with), because of that ZenGin compiles these meshes into internal compiled formats. In the case of the world it is .MSH
format and in the case of objects in the world it is the .MRM
(multi resolution mesh) with LOD information.
KrxImpExp
Blender add-on that implements support for Gothic 3D formats.
Download
ZenKit
C++ Library for loading and saving various ZenGin files (including some 3D formats).
- Read More
+ Read More
@@ -2999,13 +3008,13 @@