diff --git a/.github/workflows/dev.build.yml b/.github/workflows/dev.build.yml index e773ccf089..ace75b0b28 100644 --- a/.github/workflows/dev.build.yml +++ b/.github/workflows/dev.build.yml @@ -7,39 +7,48 @@ on: env: GMC_ENABLE_ON_PUBLISH: true + GMC_DEV_URL: 'https://auronen.cokoliv.eu/gmc/' jobs: deploy: runs-on: ubuntu-latest steps: - name: Install Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Number of commits to fetch. 0 indicates all history. # Default: 1 # 0 is needed for the update time plugin to work properly fetch-depth: 0 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: 3.12 cache: pip - - name: Cache `requirements.txt` + - name: Process Python Cache id: cache-requirements - uses: actions/cache@v3 + uses: actions/cache@v4 with: - path: '**/venv/*' - key: requirements-${{ hashFiles('**/requirements*.txt') }} - - name: Install Dependencies into `venv` + path: venv + key: requirements-${{ hashFiles('requirements*.txt') }} + - name: Install Uncached Requirements if: steps.cache-requirements.outputs.cache-hit != 'true' run: | python -m venv venv source venv/bin/activate pip install -r requirements.txt + pip install -r requirements-deploy.txt - name: Run prebuild tests run: | source venv/bin/activate python -m unittest discover tests/ -v + - name: Process MkDocs Plugins & Hooks Cache + uses: actions/cache@v4 + with: + path: .cache + key: mkdocs-${{ github.sha }} + restore-keys: | + mkdocs- - name: Build and deploy site run: | source venv/bin/activate diff --git a/.github/workflows/master.build.yml b/.github/workflows/master.build.yml index eb96c37fd4..a78e9bb751 100644 --- a/.github/workflows/master.build.yml +++ b/.github/workflows/master.build.yml @@ -13,33 +13,41 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Number of commits to fetch. 0 indicates all history. # Default: 1 # 0 is needed for the update time plugin to work properly fetch-depth: 0 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: 3.12 cache: pip - - name: Cache `requirements.txt` + - name: Process Python Cache id: cache-requirements - uses: actions/cache@v3 + uses: actions/cache@v4 with: - path: '**/venv/*' - key: requirements-${{ hashFiles('**/requirements*.txt') }} - - name: Install Dependencies into `venv` + path: venv + key: requirements-${{ hashFiles('requirements*.txt') }} + - name: Install Uncached Requirements if: steps.cache-requirements.outputs.cache-hit != 'true' run: | python -m venv venv source venv/bin/activate pip install -r requirements.txt + pip install -r requirements-deploy.txt - name: Run prebuild tests run: | source venv/bin/activate python -m unittest discover tests/ -v + - name: Process MkDocs Plugins & Hooks Cache + uses: actions/cache@v4 + with: + path: .cache + key: mkdocs-${{ github.sha }} + restore-keys: | + mkdocs- - name: Build and deploy site run: | source venv/bin/activate diff --git a/.github/workflows/pull.request.yml b/.github/workflows/pull.request.yml index 7817fee2ff..4164073b0c 100644 --- a/.github/workflows/pull.request.yml +++ b/.github/workflows/pull.request.yml @@ -13,29 +13,30 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Number of commits to fetch. 0 indicates all history. # Default: 1 # 0 is needed for the update time plugin to work properly fetch-depth: 1 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: 3.12 cache: pip - - name: Cache `requirements.txt` + - name: Process Python Cache id: cache-requirements - uses: actions/cache@v3 + uses: actions/cache@v4 with: - path: '**/venv/*' - key: requirements-${{ hashFiles('**/requirements*.txt') }} - - name: Install Dependencies into `venv` + path: venv + key: requirements-${{ hashFiles('requirements*.txt') }} + - name: Install Uncached Requirements if: steps.cache-requirements.outputs.cache-hit != 'true' run: | python -m venv venv source venv/bin/activate pip install -r requirements.txt + pip install -r requirements-deploy.txt - name: Run prebuild tests run: | source venv/bin/activate diff --git a/.gitignore b/.gitignore index f2f846fd6f..8fe757e00d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ __pycache__/ /drafts/ # Social Plugin image cache -.cache/ \ No newline at end of file +.cache/ + +# VS Code config files +.vscode/ \ No newline at end of file diff --git a/docs/.pages b/docs/.pages index ff39b93ddb..935044d41e 100644 --- a/docs/.pages +++ b/docs/.pages @@ -1,6 +1,7 @@ nav: - Home: - ... | index*.md + - ... | preferences*.md - zengin - genome - contribute \ No newline at end of file diff --git a/docs/contribute/index.md b/docs/contribute/index.md index 3a56d6f398..707a0c14e6 100644 --- a/docs/contribute/index.md +++ b/docs/contribute/index.md @@ -188,25 +188,25 @@ In order to work locally: #### Build preferences While working with the project, it's possible to set various environmental variables to configure it to your own preferences: -- `GMC_DEFAULT_LANG` - is a 2-character language identifier (it must be present in the `mkdocs.yml` file), it sets the default language of the site -- `GMC_ONLY_DEFAULT_LANG` - `True` or `False` value, activates the site build to be only in the default language +- `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: ```bash title="Linux" -export GMC_DEFAULT_LANG=en export GMC_ONLY_DEFAULT_LANG=True; mkdocs serve +export GMC_DEV_LOCALE=en export GMC_BUILD_ALTERNATES=False; mkdocs serve ``` ```powershell title="Windows Powershell" -$env:GMC_DEFAULT_LANG="en" -$env:GMC_ONLY_DEFAULT_LANG="True" +$env:GMC_DEV_LOCALE="en" +$env:GMC_BUILD_ALTERNATES="False" mkdocs serve ``` ```batch title="Windows Command Prompt (cmd)" -set GMC_DEFAULT_LANG=en -set GMC_ONLY_DEFAULT_LANG=True +set GMC_DEV_LOCALE=en +set GMC_BUILD_ALTERNATES=False mkdocs serve ``` diff --git a/docs/contribute/index.pl.md b/docs/contribute/index.pl.md index e88d2af266..e7f4c911d5 100644 --- a/docs/contribute/index.pl.md +++ b/docs/contribute/index.pl.md @@ -188,25 +188,25 @@ Aby móc pracować lokalnie: #### Preferencje budowy strony Podczas pracy z projektem można ustawić różne zmienne środowiskowe, żeby przystosować konfigurację do własnych preferencji: -- `GMC_DEFAULT_LANG` - to dwuznakowy identyfikator języka (musi być obecny w pliku `mkdocs.yml`), ustawia domyślny język strony -- `GMC_ONLY_DEFAULT_LANG` - wartość `True` albo `False`, aktywuje budowanie strony wyłącznie w domyślnym języku +- `GMC_DEV_LOCALE` - to dwuznakowy identyfikator języka (np. `en`, `pl`), ustawia język testowy. To ustawi ten języki jako domyślny oraz jedyny renderowany podczas budowy strony. Pomaga w zmniejszeniu czasu budowy strony oraz pozwala na łatwe zmienianie języka zamiast modyfikowania pliku konfiguracyjnego. **Przez zmiany w pluginie `mkdocs-static-i18n` jest to jedyny sposób na tymczasową zmianę domyślnego języka** +- `GMC_BUILD_ALTERNATES` - wartość `True` albo `False`, aktywuje budowanie strony wraz z alternatywnymi językami. Domyślnie alternatywne języki są pomijane, aby zmenijszyć czas budowy strony. - `GMC_ENABLE_ON_PUBLISH` - wartość `True` albo `False`, aktywuje wszystkie finalne procesy, jak dodanie daty ostatniej aktualizacji, minimalizacja zasobów itp. Dla otwartego okna poleceń można tymczasowo je ustawić: ```bash title="Linux" -export GMC_DEFAULT_LANG=en export GMC_ONLY_DEFAULT_LANG=True; mkdocs serve +export GMC_DEV_LOCALE=en export GMC_BUILD_ALTERNATES=False; mkdocs serve ``` ```powershell title="Windows Powershell" -$env:GMC_DEFAULT_LANG="en" -$env:GMC_ONLY_DEFAULT_LANG="True" +$env:GMC_DEV_LOCALE="en" +$env:GMC_BUILD_ALTERNATES="False" mkdocs serve ``` ```batch title="Windows Konsola Poleceń (cmd)" -set GMC_DEFAULT_LANG=en -set GMC_ONLY_DEFAULT_LANG=True +set GMC_DEV_LOCALE=en +set GMC_BUILD_ALTERNATES=False mkdocs serve ``` diff --git a/docs/genome/tools/index.md b/docs/genome/tools/index.md index 432f878d20..ccf868efcc 100644 --- a/docs/genome/tools/index.md +++ b/docs/genome/tools/index.md @@ -6,5 +6,5 @@ Piranha Bytes did not release a modkit for their Genome engine, but the modding This page is under construction, for now, only handful of links are present. ## Gothic 3 SDK -Georgeto, inspired by NiceDE'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. +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](https://github.com/georgeto/gothic3sdk) diff --git a/docs/preferences.md b/docs/preferences.md new file mode 100644 index 0000000000..5665708f12 --- /dev/null +++ b/docs/preferences.md @@ -0,0 +1,92 @@ +--- +preferences_i18n: + en: + page-title: "Preferences" + page-description: "This page allows to set various preferences for reading the docs:" + color-title: "Color" + color-description: "You can change the feel of the site with a color change." + color-input-accent-title: "Select accent color" + color-input-hue-title: "Select hue color" + color-button-reset: "Reset colors" + custom-title: "Custom CSS" + custom-description: "You can add custom stylesheets." + custom-textarea-title: "Input CSS" + font-title: "Font" + font-description: "You can change the font to another preset." + font-selection-title: "Select font" + font-selection-default: "Default" + font-selection-opendyslexic: "OpenDyslexic" + heading-shadows-title: "Heading shadows" + heading-shadows-description: "You can enable additional shadows for the heading to make them appear more bold." + pl: + page-title: "Preferencje" + page-description: "Ta strona pozwala ustawić różne preferencje do czytania dokumentacji:" + color-title: "Kolor" + color-description: "Możesz zmienić nastrój strony poprzez zmianę koloru." + color-input-accent-title: "Wybierz kolor akcentujący" + color-input-hue-title: "Wybierz kolor odcienia" + color-button-reset: "Zresetuj kolory" + custom-title: "Własny CSS" + custom-description: "Możesz dodać niestandardowe arkusze stylów." + custom-textarea-title: "Wprowadź CSS" + font-title: "Czcionka" + font-description: "Możesz zmienić czcionkę na predefiniowany." + font-selection-title: "Wybierz czcionkę" + font-selection-default: "Domyślna" + font-selection-opendyslexic: "OpenDyslexic" + heading-shadows-title: "Cienie nagłówków" + heading-shadows-description: "Możesz włączyć dodatkowe cienie do nagłówków żeby wyglądały bardziej pogrubione." +--- +# {{ page-title }} + +{{ page-description }} + +## {{ color-title }} + +{{ color-description }} + + + + + + + +[{{ color-button-reset }} :fontawesome-regular-circle-xmark:](#preference-color-reset){ #preference-color-reset .md-button data-extra="reset" data-option="color" title="{{ color-button-reset }}" } + +## {{ font-title }} + +{{ font-description }} + + + + +## {{ custom-title }} + +{{ custom-description }} +

+ +

+ + \ No newline at end of file diff --git a/docs/zengin/anims/events.md b/docs/zengin/anims/events.md index 6023b9dd04..272cdd000d 100644 --- a/docs/zengin/anims/events.md +++ b/docs/zengin/anims/events.md @@ -1,50 +1,878 @@ --- -title: EventBlocks +title: Events --- -## Animation event blocks -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. + +!!! example "Acknowledgment" + This tutorial was possible thanks to Kerrax, VAM and their excelent articles ([MDS](https://worldofplayers.ru/threads/36653/), [EventTags](https://worldofplayers.ru/threads/37708/)) and Avallach from [theModders](http://themodders.org/index.php?topic=13214.0) who provided valuable insight. + +## Animation event block overview + +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: ```dae -ani ("s_RunL" 1 "s_RunL" 0.0 0.1 M. "Hum_RunLoop_M01.asc" F 12 31) +ani ("s_RunL" 1 "s_RunL" 0.0 0.1 M. "Hum_RunLoop_M01.asc" F 12 31) // animation +{ // event block start + + *eventSFXGrnd (12 "Run") // animation event + *eventSFXGrnd (24 "Run") // animation event + ... + *eventSFXGrnd (30 "Run") // animation event +} // event block end +``` + +!!! 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. + +## Animation events +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: +```dae + *EVENTNAME (FRAME KEYWORD "INSTANCE" [OPTIONAL] [A:VALUE] [B:VALUE]) +``` + +`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](#eventcamtremor) | camera shake | +| [eventMMStartAni](#eventmmstartani) | start morph-mesh | +| [eventPFX](#eventpfx) | create particle effect | +| [eventPFXStop](#eventpfxstop) | destroy particle effect | +| [eventSwapMesh](#eventswapmesh) | exchange item meshes between two slots | +| [eventSFX](#eventsfx) | create sound effect | +| [eventSFXGRND](#eventsfxgrnd) | create sound effect on the ground | +| [eventTag](#eventtag) | generic event, does action specified in parameters | +| Defined in engine but never used ? | | +| [eventPFXGRND](#eventpfxgrnd) | create particle effect on the ground | +| [eventSetMesh](#eventsetmesh) | ? | +| [modelTag](#modeltag) | same as eventTag, but applies to morphmesh? | + + +### eventCamTremor + +Earthquake effect (camera shake) + +Example: +```dae +*eventCamTremor (12 1000 500 2 8 ) +``` + +Syntax: +```dae +*eventCamTremor (FRAME RANGE DURATION MIN_AMPLIFIER MAX_AMPLIFIER) +``` + +`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. + +### eventMMStartAni + +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: +```dae +*eventMMStartAni (14 "T_HURT") +*eventMMStartAni (6 "S_SHOOT" "ZS_RIGHTHAND") +*eventMMStartAni (6 "S_BOOK_NEXT_PAGE" "ZS_RIGHTHAND" I:0.5 H:5) +``` + +Syntax: +```dae +*eventMMStartAni (FRAME "ANI_NAME" ["NODE_NAME"] [I:INTENSITY] [H:HOLD_TIME]) +``` + + +`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 + +## eventPfx + +Start particle effect at the specified bone. + +Example: +```dae +*eventPFX (12 "ZMODELLANDDUST" "Bip01" ) +*eventPFX (2 1 "DEMON_ATTACK" "BIP01 R HAND" ATTACH) +``` + +Syntax: +```dae +*eventPFX (FRAME [PFX_HANDLE] "PFX_NAME" "NODE_NAME" [ATTACH]) +``` + +`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](#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. + + +## eventPFXStop + +Stops particle effect previously started by [eventPfx](#eventpfx) + + +Example: +```dae +*eventPFX (2 1 "DEMON_ATTACK" "BIP01 R HAND" ATTACH) // starts pfx with handle 1 +... +*eventPFXStop (70 1) // stops pfx started above +``` + +Syntax: +```dae +*eventPFXStop (FRAME PFX_HANDLE) +``` + +`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](#eventpfx) first + + +## eventSwapMesh + +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: +```dae +*eventSwapMesh (5 "ZS_CROSSBOW" "ZS_LEFTARM") +``` + +Syntax: +```dae +*eventSWAPMESH (FRAME "SOURCE_NODE_NAME" "TARGET_NODE_NAME") +``` + +`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 + +## eventSfx + +Play sound effect. It can be either `SFX` instance from scripts, or `.WAV` file. + +Example: +```dae +*eventSFX (0 "Drown") +*eventSFX (8 "WHOOSH" EMPTY_SLOT) +*eventSFX (8 "BAB_SIGH" R:5000 EMPTY_SLOT) +``` + +Syntax: +```dae +*eventPFX (FRAME "SFX_NAME" [R:RANGE] [EMPTY_SLOT]) +``` + +`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 + + +## eventSfxGrnd + +the same as [eventSfx](#eventsfx) with only one difference, the sound effect name is appended with the current material name. + +Example: +```dae +*eventSFXGrnd (12 "Run") +``` + +Syntax: +```dae +*eventSFXGrnd (FRAME "SFX_NAME" [R:RANGE] [EMPTY_SLOT]) +``` + +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 | ✔️ | ✔️ | +| `EARTH` | _Earth | ✔️ | ✔️ | +| `SAND` | _Sand | ✔️ | ✔️ | +| `METAL` | _Metal | ✔️ | ✔️ | +| `WATER` | _Water | ✔️ | ✔️ | +| `WOOD` | _Wood | ✔️ | ✔️ | +| `SNOW` | _Snow | ❌ | ✔️ | +| `STONE` | _Stone | ✔️ | ✔️ | +| default | _Stone | ✔️ | ✔️ | + + +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. + + +## eventTag + +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: +```dae +*eventTag (FRAME "EVENT_TAG_TYPE" "PARAMETER_1" "PARAMETER_2" ... "PARAMETER_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](#def_create_item) | Creates item into slot | +| [DEF_INSERT_ITEM](#def_insert_item) | Inserts item to slot from inventory | +| [DEF_REMOVE_ITEM](#def_remove_item) | Removes item from slot to inventory | +| [DEF_DESTROY_ITEM](#def_destroy_item) | Destroys item in slot | +| [DEF_PLACE_ITEM](#def_place_item) | ~~Places item from slot into mob slot~~ Destroys item in slot | +| [DEF_EXCHANGE_ITEM](#def_exchange_item) | Removes item in slot and replaces with new item | +| [DEF_FIGHTMODE](#def_fightmode) | Sets npc into weapon stance | +| [DEF_PLACE_MUNITION](#def_place_munition) | Inserts munition into slot | +| [DEF_REMOVE_MUNITION](#def_remove_munition) | Remove munition back to inventory | +| [DEF_DRAWSOUND](#def_drawsound) | Plays weapon drawing sound based on weapon material | +| [DEF_UNDRAWSOUND](#def_undrawsound) | Plays weapon sheating sound based on weapon material | +| [DEF_SWAPMESH](#def_swapmesh) | Moves items visual to different slot visually | +| [DEF_DRAWTORCH](#def_drawtorch) | Inserts torch | +| [DEF_INV_TORCH](#def_inv_torch) | Moves torch to different slot temporarily | +| [DEF_DROP_TORCH](#def_drop_torch) | Drops torch from slot to world | +| [DEF_HIT_LIMB](#def_hit_limb) | Defines node which deals damage | +| [DEF_DIR](#def_dir) | Defines attack direction | +| [DEF_DAM_MULTIPLIER](#def_dam_multiplier) | Defines damage mutliplier | +| [DEF_PAR_FRAME](#def_par_frame) | Defines frame range for blocking | +| [DEF_OPT_FRAME](#def_opt_frame) | Defines damage frames | +| [DEF_HIT_END](#def_hit_end) | Defines last frame to continue combo | +| [DEF_WINDOW](#def_window) | Defines frame for combo continuation | + +#### DEF_CREATE_ITEM + +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: +```dae +*eventTag (4 "DEF_CREATE_ITEM" "ZS_RIGHTHAND" "ItMw_1H_Mace_L_04") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_CREATE_ITEM" "SLOT" "ITEM_INSTANCE") +``` + + +`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 + +#### DEF_INSERT_ITEM + +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: +```{ .dae } +ani ("t_BSANVIL_S0_2_S1" 1 "s_BSANVIL_S1" 0.0 0.0 M. "Hum_BSAnvil_Jue00.asc" F 4 9) { - *eventSFXGrnd (12 "Run") - *eventSFXGrnd (21 "Run") + *eventTag (4 "DEF_INSERT_ITEM" "ZS_LEFTHAND") // (1) + *eventTag (4 "DEF_CREATE_ITEM" "ZS_RIGHTHAND" "ItMw_1H_Mace_L_04") // (2) } ``` -The example shows the animation and its event block. We place these events into a block surrounded by curly brackets. -There are many events to choose from to choose from. Here are some examples: -Sound effects +Syntax: ```dae -*eventSFXGrnd (12 "Run") -*eventSFX (10 "Swim") +*eventTag (FRAME "DEF_INSERT_ITEM" "SLOT") +``` + + +`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 + +!!! Note "" + 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. + +#### DEF_REMOVE_ITEM + +Remove an item inserted into a slot via `DEF_INSERT_ITEM` from the slot back into the **inventory**. + +Example: +```dae +*eventTag (0 "DEF_REMOVE_ITEM") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_REMOVE_ITEM") +``` + +!!! Warning + This event tag most likely works only during Mob/Item interaction + +#### DEF_DESTROY_ITEM + +Destroys an item inserted into a slot via `DEF_INSERT_ITEM`. The item is **removed** from the world. + +Example: +```dae +*eventTag (0 "DEF_DESTROY_ITEM") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DESTROY_ITEM") +``` + +!!! Warning + This event tag most likely works only during Mob/Item interaction + +#### DEF_PLACE_ITEM + +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: +```dae +*eventTag (0 "DEF_PLACE_ITEM") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_PLACE_ITEM") +``` + +!!! Warning + This event tag most likely works only during Mob/Item interaction + +??? Example "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. + + ```dae + // Sleeper Portal + ani ("t_SPORTAL_Stand_2_S0" 1 "s_SPORTAL_S0" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 0 19) + ani ("s_SPORTAL_S0" 1 "s_SPORTAL_S0" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 20 20) + ani ("t_SPORTAL_S0_2_Stand" 1 "" 0.0 0.2 M. "Hum_SleeperPortal_M01.asc" R 0 19) + ani ("t_SPORTAL_S0_2_S1" 1 "s_SPORTAL_S1" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 21 90 FPS:10) + { + *eventTag (60 "DEF_INSERT_ITEM" "ZS_RIGHTHAND") // (1) + *eventTag (90 "DEF_PLACE_ITEM") // (2) + } + ani ("s_SPORTAL_S1" 1 "s_SPORTAL_S1" 0.0 0.0 M. "Hum_SleeperPortal_M01.asc" F 91 91) + ani ("t_SPORTAL_S1_2_Stand" 1 "" 0.0 0.2 M. "Hum_SleeperPortal_M01.asc" F 90 100) + ``` + + 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. + +#### DEF_EXCHANGE_ITEM + +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: +```dae +*eventTag (37 "DEF_EXCHANGE_ITEM" "ZS_LEFTHAND" "ItMiSwordrawhot") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_EXCHANGE_ITEM" "SLOT" "ITEM_INSTANCE") ``` -Particle effects + +`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 + +#### DEF_FIGHTMODE + +Set fight mode for the model. Used in transition animations to weapon stances like `t_1h_2_1hRun`. + +Example: ```dae -*eventPFX (12 "ZMODELLANDDUST" "Bip01") -*eventPFX (35 1 "BUBBLES" "BIP01 HEAD" ATTACH) -*eventPFXStop (45 1) +*eventTag (5 "DEF_FIGHTMODE" "FIST") ``` -Morph mesh animations -> ⚠ Heads are animated using morph meshes and whilst this feature is almost never used in the original game, Chronicles of Myrtana uses it plenty. I intend to dedicate separate section to `morphMesh` animation in the future. +Syntax: ```dae -*eventMMStartAni (14 "T_HURT") +*eventTag (FRAME "DEF_FIGHTMODE" "FIGHT_MODE") ``` -Event tags + +`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` + +#### DEF_PLACE_MUNITION + +Place ammunition, from inventory such as an arrow into the specified slot. Used in reloading animations after a bow/crossbow shot. + +Example: ```dae -*eventTag (5 "DEF_FIGHTMODE" "") +*eventTag (9 "DEF_PLACE_MUNITION" "ZS_RIGHTHAND") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_PLACE_MUNITION" "SLOT") +``` -*eventTag (0 "DEF_HIT_LIMB" "ZS_RIGHTHAND") -*eventTag (0 "DEF_OPT_FRAME" "6") -*eventTag (0 "DEF_HIT_END" "29") -*eventTag (0 "DEF_WINDOW" "18 35") +`SLOT` - slot where the ammunition is created. There are only two valid slot names: `"ZS_LEFTHAND"` and `"ZS_RIGHTHAND"`. -*eventTa (4 "DEF_INSERT_ITEM" "ZS_LEFTHAND") -*eventTa (4 "DEF_CREATE_ITEM" "ZS_RIGHTHAND" "ItMw_1H_Sledgehammer_01") -*eventTa (9 "DEF_EXCHANGE_ITEM" "ZS_LEFTHAND" "ItMiSwordbladehot") -*eventTa (4 "DEF_REMOVE_ITEM") +Ammunition always corresponds to the equipped ranged weapon instance and its `munition` field in the `C_ITEM` instance + +```dae hl_lines="10" +instance ItRw_Sld_Bow(C_Item) +{ + name = "Лук"; + mainflag = ITEM_KAT_FF; + flags = ITEM_BOW; + material = MAT_WOOD; + value = Value_SldBogen; + damageTotal = Damage_SldBogen; + damagetype = DAM_POINT; + munition = ItRw_Arrow; + cond_atr[2] = ATR_DEXTERITY; + cond_value[2] = Condition_SldBogen; + visual = "ItRw_Sld_Bow.mms"; + description = name; + text[2] = NAME_Damage; + count[2] = damageTotal; + text[3] = NAME_Dex_needed; + count[3] = cond_value[2]; + text[5] = NAME_Value; + count[5] = value; +}; ``` +#### DEF_REMOVE_MUNITION + +Remove ammunition previously placed by [DEF_PLACE_MUNITION](#def_place_munition) event + +Example: +```dae +*eventTag (19 "DEF_REMOVE_MUNITION") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_REMOVE_MUNITION") +``` + +#### DEF_DRAWSOUND + +Play weapon drawing sound. Determined by drawn weapon `material` field in the `C_ITEM` instance + + - `“DrawSound_WO.wav”` - for MAT_WOOD; + - `"DrawSound_ME.wav"` - for MAT_METAL. + + +Example: +```dae +*eventTag (19 "DEF_DRAWSOUND") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DRAWSOUND") +``` + +#### DEF_UNDRAWSOUND + +Play weapon sheathing sound. Determined by drawn weapon `material` field in the `C_ITEM` instance + + - `"UndrawSound_WO.wav”` - for MAT_WOOD; + - `"UndrawSound_ME.wav"` - for MAT_METAL. + + +Example: +```dae +*eventTag (19 "DEF_UNDRAWSOUND") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_UNDRAWSOUND") +``` + +#### DEF_SWAPMESH + +Swap items in the specified slots. + +Example: +```dae +*eventTag (5 "DEF_SWAPMESH" "ZS_CROSSBOW" "ZS_LEFTHAND") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_SWAPMESH" "SLOT1" "SLOT2") +``` + +`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](#def_fightmode) event. This can lead to game freezing. + +!!! Tip + This event is similar to the [*eventSwapMesh](#eventswapmesh). The main difference is [*eventSwapMesh](#eventswapmesh) will swap only visuals (meshes) of the items, while [eventTag DEF_SWAPMESH](#def_swapmesh) will swap items and their slot references. + After a game reload, meshes would reset their positions if swapped using [*eventSwapMesh](#eventswapmesh). Additionally [*eventSwapMesh](#eventswapmesh) does not try to set the model into fight mode. + +#### DEF_DRAWTORCH + +Does nothing? never used. + +Example: +```dae +*eventTag (5 "DEF_DRAWTORCH") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DRAWTORCH") +``` + +#### DEF_INV_TORCH + +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: +```dae +*eventTag (5 "DEF_INV_TORCH") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_INV_TORCH") +``` + +#### DEF_DROP_TORCH + +Drop the torch onto the ground if present in `ZS_LEFTHAND`. + +Example: +```dae +*eventTag (5 "DEF_DROP_TORCH") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DROP_TORCH") +``` + +#### DEF_HIT_LIMB + +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: +```dae +// humans - fist attacks +*eventTag (0 "DEF_HIT_LIMB" "BIP01 R HAND") +// humans - sword attacks +*eventTag (0 "DEF_HIT_LIMB" "ZS_RIGHTHAND") +// animals +eventTag (0 "DEF_HIT_LIMB" "BIP01 HEAD") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_HIT_LIMB" "SLOT1" "SLOT2" "SLOT3" "SLOT4") +``` + +#### DEF_DIR + +Set the direction of the attack. Enemy block animation is determined by this information. Not used. + +Example: +```dae +*eventTag (0 "DEF_DIR" "O") +*eventTag (0 "DEF_DIR" "L") +*eventTag (0 "DEF_DIR" "OUOL") // combo attack - top, under, +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DIR" "DIRECTIONS") +``` + +`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 + +- `O` - (oben) from top/ over + +- `U` - (unter) from under + +- `R` - from right + +- `L` - from left + +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. + + +#### DEF_DAM_MULTIPLIER + +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: +```dae +*eventTag (0 "DEF_DAM_MULTIPLIER" "0.2") +*eventTag (0 "DEF_DAM_MULTIPLIER" "2.0") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_DAM_MULTIPLIER" "MULTIPLIER") +``` + +`MULTIPLIER` - float value inside quotes + +#### DEF_PAR_FRAME + +Set frame range during which damage is blocked. If not provided whole animation is blocking damage. + +Example: +```dae +*eventTag (0 "DEF_PAR_FRAME" "1 8") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_PAR_FRAME" "START_FRAME_END_FRAME") +``` + +`START_FRAME_END_FRAME` - Two integer numbers inside quotes. if `"0 0"` is provided, the animation will be blocking it's whole duration + +#### DEF_OPT_FRAME + +Set frames during which damage collisions should be evaluated. Damage is checked for collision with ["hit limb"](#def_hit_limb). This event usually comes in pair with eventTags [DEF_WINDOW](#def_window) and [DEF_HIT_END](#def_hit_end) + +Example: +```dae +*eventTag (0 "DEF_OPT_FRAME" "6") // on hit attack, hit on 6th frame +*eventTag (0 "DEF_OPT_FRAME" "6 30") // 2 attack combo, hit at 6th and 30th frame +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_OPT_FRAME" "HIT_FRAME1 HIT_FRAME2 ... HIT_FRAME10") +``` + +`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). + + +#### DEF_HIT_END + +Set frames at which the combo is “cut off” if you do not press the “up” 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’s characteristic twitching. +The number of frames specified in this entry must match the number of frames of the [eventTag DEF_OPT_FRAME](#def_opt_frame). + +Example: +```dae +*eventTag (0 "DEF_HIT_END" "32") +*eventTag (0 "DEF_HIT_END" "27 48 75") +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_HIT_END" "HIT_END1 HIT_END2 ... HIT_END10") +``` + +`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 + +#### DEF_WINDOW + +Set a “window” in the animation - an interval of frames during which you need to press the “up” (G1) or the left mouse button (G2) to continue the combo strike. + +Example: +```dae +*eventTag (0 "DEF_WINDOW" "9 19") // one combo with window from 9-19 (can be chained) +*eventTag (0 "DEF_WINDOW" "10 23 32 41 58 70") // 3 combos with windows 10-23 then 32-41, 58-70 +``` + +Syntax: +```dae +*eventTag (FRAME "DEF_WINDOW" "HIT_1_WINDOW_START HIT_1_WINDOW_END HIT_2_WINDOW_START HIT_2_WINDOW_END ...") +``` + +`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](#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 + + +#### Attack eventTags explained + +This is original attack combo from Gothic 1 + +```dae +ani ("s_1hAttack" 1 "s_1hAttack" 0.0 0.1 M. "Hum_1hAttackComboT3_M05.asc" F 1 114) +{ + *eventTag (0 "DEF_HIT_LIMB" "ZS_RIGHTHAND") + *eventTag (0 "DEF_OPT_FRAME" "4 36 73 107") + *eventTag (0 "DEF_HIT_END" "31 63 95 113") + *eventTag (0 "DEF_WINDOW" "10 33 42 65 78 97 110 113") + *eventSFX (4 "Whoosh" EMPTY_SLOT ) + *eventSFX (72 "BACK" EMPTY_SLOT ) +} + +``` + +I will edit it slightly to make it more readable. Let's focus on the DEF_OPT_FRAME, DEF_HIT_END, + +```dae +ani ("s_1hAttack" 1 "s_1hAttack" 0.0 0.1 M. "Hum_1hAttackComboT3_M05.asc" F 1 114) +{ + ... + *eventTag (0 "DEF_OPT_FRAME" "4 36 73 107 ") + *eventTag (0 "DEF_HIT_END" " 31 63 95 113") + *eventTag (0 "DEF_WINDOW" " 10 33 42 65 78 97 110 113") + ... +} +``` + +Let's focus only on the first combo. + +```dae +ani ("s_1hAttack" 1 "s_1hAttack" 0.0 0.1 M. "Hum_1hAttackComboT3_M05.asc" F 1 114) +{ + ... + *eventTag (0 "DEF_OPT_FRAME" "4 ...") + *eventTag (0 "DEF_HIT_END" " 31 ...") + *eventTag (0 "DEF_WINDOW" " 10 33 ...") + ... +} +``` + +| 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 | + + + + + +## eventPfxGrnd + +Not used anywhere in the original game. Could possibly spawn particle effect like [eventPfx](#eventpfx) but with an added suffix similar to how [eventSfxGrnd](#eventsfxgrnd) works. Needs to be investigated. + +Syntax: +```dae +*eventPFXGRND (FRAME) +``` + +## eventSetMesh + +Unknown + +Syntax: +```dae +*eventSETMESH (FRAME "NODE_NAME") +``` + +## modelTag + +Should work similarly to [eventTag](#eventtag), but can be defined inside aniEnum block and applies to all animations of the Model. + +Syntax: +```dae +*modelTag (FRAME "EVENT_TAG_TYPE" "PARAMETER1" "PARAMETER2" "PARAMETER3" "PARAMETER4" ... ) +``` \ No newline at end of file diff --git a/docs/zengin/general_info/object_persistence.md b/docs/zengin/general_info/object_persistence.md index 2e339b8805..d64b1cbbaa 100644 --- a/docs/zengin/general_info/object_persistence.md +++ b/docs/zengin/general_info/object_persistence.md @@ -45,7 +45,7 @@ This property might not be present in older archives. 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 ;) ). +- **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](../tools/zSpy.md) ;) ). - **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. diff --git a/docs/zengin/music.md b/docs/zengin/music.md index 3705bebb97..397edcc02a 100644 --- a/docs/zengin/music.md +++ b/docs/zengin/music.md @@ -18,3 +18,7 @@ The music directory contains these file types: - Patterns - fragments of tracks, that can be later merged, looped and superimposed on each other - `.sgt` - File with properly connected patterns - the final track + +## Alternative Music System + +The [zBassMusic](./union/plugins/zbassmusic.md) 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. \ No newline at end of file diff --git a/docs/zengin/music.pl.md b/docs/zengin/music.pl.md new file mode 100644 index 0000000000..2a29ce3669 --- /dev/null +++ b/docs/zengin/music.pl.md @@ -0,0 +1,27 @@ +--- +title: Muzyka +--- +# Muzyka + +Zengin używa [DirectMusic](https://en.m.wikipedia.org/wiki/DirectMusic) do odtwarzania ścieżki dźwiękowej w grze. Aby edytować pliki muzyczne Gothica, potrzebujesz programu [Direct Music Producer](https://en.m.wikipedia.org/wiki/DirectMusic), który został wydany przez Microsoft i był dostarczany do starszych zestawów SDK DirectX. + +!!! Warning "Ostrzeżenie" + Pliki muzyczne nie mogą być spakowane do archiwów `.vdf` lub `.mod`, wszystkie takie pliki muszą znajdować się w katalogu `/_work/Data/Music`. + +## Formaty plików + +Katalog `Music` zawiera następujące typy plików: + +- `.dls` - Plik formatu [Downloadable Sound](https://en.wikipedia.org/wiki/DLS_format). Jest bazą dla wszystkich innych plików. Zawiera: + - Kolekcje wirtualnych instrumentów muzycznych. + - Pliki `.wav` używane przez instrumenty. + +- `.sty` - Plik stylu. Zawiera: + - Zespoły (Bands) - ustawienia instrumentów wirtualnych z `.dls`. + - Wzory (Patterns) - fragmenty utworów, które można później łączyć, zapętlać i nakładać na siebie. + +- `.sgt` - Plik z odpowiednio połączonymi wzorami (patternami) - końcowy utwór + +## Alternatywny System Muzyczny + +Plugin [zBassMusic](./union/plugins/zbassmusic.md) zastępuje domyślną bibliotekę muzyczną Zengina, dużo nowszą biblioteką BASS. Umożliwia to między innymi odtwarzanie muzyki w takich formatach jak `.mp3` lub `.ogg`, oraz pakownie utworów do archiwów `.vdf` i `.mod`. \ No newline at end of file diff --git a/docs/zengin/scripts/classes/c_item.md b/docs/zengin/scripts/classes/c_item.md index ea5757085b..741c1ee5b2 100644 --- a/docs/zengin/scripts/classes/c_item.md +++ b/docs/zengin/scripts/classes/c_item.md @@ -41,7 +41,7 @@ Class definition as it is defined in [`Scripts/Content/_intern/Classes.d`](https // Benötigte Attribute zum Benutzen des Items var int cond_atr[3]; // Array of NPC attributes needed to equip the item - var int cond_value[3]; // Array of values corresponding to the cond_atr arry + var int cond_value[3]; // Array of values corresponding to the cond_atr array // Attributes to be changed on equip var int change_atr[3]; // Array of attributes that will be changed on equip diff --git a/docs/zengin/scripts/classes/c_menu.md b/docs/zengin/scripts/classes/c_menu.md new file mode 100644 index 0000000000..cf75021448 --- /dev/null +++ b/docs/zengin/scripts/classes/c_menu.md @@ -0,0 +1,179 @@ +--- +title: C_MENU +--- + +# C_MENU Daedalus class + +!!! example "Acknowledgment" + Heavily inspired by the amazing documentation site [Gothic library](http://www.gothic-library.ru) + +Class `C_Menu` is responsible for the behavior and properties of the game menus (options, save etc.). +## Class definition +Class definition as it is defined in [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d) script file. + +??? "C_Menu Daedalus class" + ```dae + class C_Menu + { + var string backPic; // Menu background image + var string backWorld; // Background ZEN-world of the game menu (Not used) + var int posx; // The top left point of the menu on the screen horizontally (X-axis) + var int posy; // The top left point of the menu on the screen vertically (Y-axis) + var int dimx; // Menu width in virtual coordinates + var int dimy; // Menu height in virtual coordinates + var int alpha; // Menu transparency + var string musicTheme; // Music track of the menu + var int eventTimerMSec; // trigger time for the event EVENT_TIMER + var string items[150]; // Menu items + var int flags; // Menu flags + var int defaultOutGame; // Menu item highlighted by default when the game is not running + var int defaultInGame; // Menu item highlighted by default when the game is running + }; + ``` + +## Class members + +| Variable | Type | Description | +|-----------------------------------|--------|-------------------------------------------------------------------------------------| +| [backPic](#backpic) | string | Menu background image | +| [backWorld](#backworld) | string | Background ZEN-world of the game menu (Not used) | +| [posx](#posx) | int | The top left point of the menu on the screen horizontally (X-axis) | +| [posy](#posy) | int | The top left point of the menu on the screen vertically (Y-axis) | +| [dimx](#dimx) | int | Menu width in virtual coordinates | +| [dimy](#dimy) | int | Menu height in virtual coordinates | +| [alpha](#alpha) | int | Menu transparency | +| [musicTheme](#musictheme) | string | Music track of the menu | +| [eventTimerMSec](#eventtimermsec) | int | The timer that triggered the event in seconds | +| [items](#items) | string | Menu items | +| [flags](#flags) | int | Menu flags | +| [defaultOutGame](#defaultoutgame) | int | Menu item highlighted by default when the game is not running | +| [defaultInGame](#defaultingame) | int | Menu item highlighted by default when the game is running | + + +## Class member overview +Description of the class member variables. + +### backPic +`backPic` is just a name of background image of the menu in `.tga` format. + +### backWorld +!!! Warning "Deprecated setting" + The background world of the game menu in `.ZEN` format. + +### posx +The horizontal position of the top left point of the menu on the screen, in virtual coordinates. + +### posy +The vertical position of the top left point of the menu on the screen, in virtual coordinates. + +### dimx +Menu width in virtual coordinates. + +### dimy +Menu height in virtual coordinates. + +### alpha +Menu transparency. Accepts values ​​from 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. + +### musicTheme +Music theme of the menu. +```dae +instance MENU_MAIN(C_MENU_DEF) +{ + ... + musictheme = "SYS_Menu"; + ... +}; +``` +All instances of musical themes are stored in a file [`Scripts/System/Music/MusicInst.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/Music/MusicInst.d) + +### eventTimerMSec +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`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L51) + +```dae +const int EVENT_UNDEF = 0; // Undefined +const int EVENT_EXECUTE = 1; // Process start event +const int EVENT_CHANGED = 2; // Menu parameter change event +const int EVENT_LEAVE = 3; // Menu item focus loss event +const int EVENT_TIMER = 4; // Timer fire event +const int EVENT_CLOSE = 5; // Menu close event +const int EVENT_INIT = 6; // Initialization event +const int EVENT_SEL_PREV = 7; // Select event of the previous menu item +const int EVENT_SEL_NEXT = 8; // Select event of the next menu item +``` + +### items +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. + +```dae +// Menu +instance MENU_MAIN(C_MENU_DEF) +{ + ... + items[0] = "MENUITEM_MAIN_HEADLINE"; + items[1] = "MENUITEM_MAIN_HEADLINE2"; + items[2] = "MENUITEM_MAIN_NEWGAME"; + ... +}; + +// Menu elements: labels, checkboxes, sliders, etc. + +instance MENUITEM_MAIN_HEADLINE(C_MENU_ITEM_DEF) +{ + ... +}; + +instance MENUITEM_MAIN_HEADLINE2(C_MENU_ITEM_DEF) +{ + ... +}; + +instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) +{ + ... +}; +``` + +### flags +Menu flags. + +The list of flag constants can be found in the file [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L43) + + +```dae +const int MENU_OVERTOP = 1; // Show menu over previous menu or in game +const int MENU_EXCLUSIVE = 2; // Close all previous menus. Only the active menu is displayed +const int MENU_NOANI = 4; // No animation +const int MENU_DONTSCALE_DIM = 8; // Don't Scale Menu Sizes +const int MENU_DONTSCALE_POS = 16; // Empty flag +const int MENU_ALIGN_CENTER = 32; // Center Align Menu +const int MENU_SHOW_INFO = 64; // Display information at the bottom of the description menu from menu items text[1] +``` + +- **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]`. + +### defaultOutGame +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. + +### defaultInGame +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. + diff --git a/docs/zengin/scripts/classes/c_menuitem.md b/docs/zengin/scripts/classes/c_menuitem.md new file mode 100644 index 0000000000..a8b04deb25 --- /dev/null +++ b/docs/zengin/scripts/classes/c_menuitem.md @@ -0,0 +1,765 @@ +--- +title: C_MENU_ITEM +--- + +# C_MENU_ITEM Daedalus class + +!!! example "Acknowledgment" + Heavily inspired by the amazing documentation site [Gothic library](http://www.gothic-library.ru) + +Class `C_Menu_Item` describes the elements of the game menu (sliders, checkboxes, buttons, etc.) . +## Class definition +Class definition as it is defined in [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d) script file. + +??? "C_Menu_Item Daedalus class" + ```dae + CONST INT MAX_USERSTRINGS = 10; + CONST INT MAX_ITEMS = 150; + CONST INT MAX_EVENTS = 10; + CONST INT MAX_SEL_ACTIONS = 5; + CONST INT MAX_USERVARS = 4; + + class C_Menu_Item + { + var string fontName; // Font of the menu item. + var string text[MAX_USERSTRINGS]; // Text of the interface element. + var string backPic; // Background image of menu items. + var string alphaMode; // Transparency blending mode of menu items. + var int alpha; // Transparency of the menu item. + var int type; // Type of the interface element. + var int onSelAction[MAX_SEL_ACTIONS]; // Array of commands executed when selecting the menu item. + var string onSelAction_S[MAX_SEL_ACTIONS]; // Arguments for commands specified in the onSelAction property. + var string onChgSetOption; // Gothic.ini file parameter modified by this menu item. + var string onChgSetOptionSection; // Section of the Gothic.ini file where the modified parameter is located. + var func onEventAction[MAX_EVENTS]; // Call the required function by a constant identifier. + var int posx; // Top-left point of the menu item on the screen horizontally (X-axis). + var int posy; // Top-left point of the menu item on the screen vertically (Y-axis). + var int dimx; // Width of the menu item in virtual coordinates. + var int dimy; // Height of the menu item in virtual coordinates. + var float sizeStartScale; // Initial size of the item. Not used. + var int flags; // Flags of the menu item. + var float openDelayTime; // Delay before opening the item. Not used. + var float openDuration; // Opening time. Not used. + var float userFloat[MAX_USERVARS]; // Digital settings of menu items. + var string userString[MAX_USERVARS]; // String settings of menu items. + var int frameSizeX; // Text offset inside the frame on the X-axis. + var int frameSizeY; // Text offset inside the frame on the Y-axis. + var string hideIfOptionSectionSet; // Section of Gothic.ini file where the option determining the display of this menu item is located. + var string hideIfOptionSet; // Gothic.ini file parameter determining the display of this menu item. + var int hideOnValue; // Value of the Gothic.ini file parameter at which this interface element is not displayed. + }; + ``` + +## Class members + +| Property | Type | Description | +|---------------------------------|--------|-------------------------------------------------------------------------| +| [fontName](#fontname) | string | Font of the menu item. | +| [text](#text) | string | Text of the interface element. | +| [backPic](#backpic) | string | Background image of menu items. | +| [alphaMode](#alphamode) | string | Transparency blending mode of menu items. | +| [alpha](#alpha) | int | Transparency of the menu item. | +| [type](#type) | int | Type of the interface element. | +| [onSelAction](#onselaction) | int | Array of commands executed when selecting the menu item. | +| [onSelAction_S](#onselaction_s) | string | Arguments for commands specified in the onSelAction property. | +| [onChgSetOption](#onchgsetoption) | string | Gothic.ini file parameter modified by this menu item. | +| [onChgSetOptionSection](#onchgsetoptionsection) | string | Section of the Gothic.ini file where the modified parameter is located. | +| [onEventAction](#oneventaction) | Func | Call the required function by a constant identifier. | +| [posx](#posx) | int | Top-left point of the menu item on the screen horizontally (X-axis). | +| [posy](#posy) | int | Top-left point of the menu item on the screen vertically (Y-axis). | +| [dimx](#dimx) | int | Width of the menu item in virtual coordinates. | +| [dimy](#dimy) | int | Height of the menu item in virtual coordinates. | +| [sizeStartScale](#sizestartscale) | float | Initial size of the item. Not used. | +| [flags](#flags) | int | Flags of the menu item. | +| [openDelayTime](#opendelaytime) | float | Delay before opening the item. Not used. | +| [openDuration](#openduration) | float | Opening time. Not used. | +| [userFloat](#userfloat) | float | Digital settings of menu items. | +| [userString](#userstring) | string | String settings of menu items. | +| [frameSizeX](#framesizex) | int | Text offset inside the frame on the X-axis. | +| [frameSizeY](#framesizey) | int | Text offset inside the frame on the Y-axis. | +| [hideIfOptionSectionSet](#hideifoptionsectionset) | string | Section of Gothic.ini file where the option determining the display of this menu item is located. | +| [hideIfOptionSet](#hideifoptionset) | string | Gothic.ini file parameter determining the display of this menu item. | +| [hideOnValue](#hideonvalue) | int | Value of the Gothic.ini file parameter at which this interface element is not displayed. | + +## Class member overview + +Description of the class member variables. + +### fontName +`*.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. + +### text +Text inside a menu item. + +Used to determine possible values ​​for game settings. See [onChgSetOptionSection](#onchgsetoptionsection). + +Also used to display hints about the item at the bottom of the menu when the `MENU_SHOW_INFO` [flag](#flags) is set. + +```dae +// Text displayed in the element + +text[0] = "New Game"; + +// Text in the interface element responsible for game settings +// One of the presented options is displayed + +text[0] = "off|on"; + +// Tooltip for the selected element +// Index 1 is used for tooltips, not 0 + +text[1] = "Start a new adventure"; +``` + +### backPic +Background image of the menu item in `*.TGA` format. + +```dae +instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) +{ + backpic = "Inv_Slot_Highlighted.tga"; +} +``` + +### alphaMode +Texture transparency blending mode. Used in conjunction with the [alpha](#alpha) property. This parameter's value is ignored if the [backPic](#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. + +### alpha +Menu element transparency. Accepts values ​​from 0 to 255. Without specifying the [backPic](#backpic) property, the value of this parameter is ignored. + +The alpha channel rendering mode is determined using the [alphaMode](#alphamode) property. + +### type +Interface element type. Some interface elements have their own settings determined by the [userFloat](#userfloat) and [userString](#userstring) properties. + +Constants for menu item types are described in the file [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L18-L25). + +```dae +CONST INT MENU_ITEM_UNDEF = 0; // Undefined +CONST INT MENU_ITEM_TEXT = 1; // Text +CONST INT MENU_ITEM_SLIDER = 2; // Slider +CONST INT MENU_ITEM_INPUT = 3; // Input field +CONST INT MENU_ITEM_CURSOR = 4; +CONST INT MENU_ITEM_CHOICEBOX = 5; // Checkbox +CONST INT MENU_ITEM_BUTTON = 6; // Button +CONST INT MENU_ITEM_LISTBOX = 7; // Frame +``` + +- `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](#flags). + +- `MENU_ITEM_SLIDER` + Menu item type "Slider". Additional settings are provided for the slider. + - [`userFloat[0]`](#userfloat) property determines the number of divisions for the slider. + - [`userFloat[1]`](#userfloat) property determines the width of the slider. + - [`userString[0]`](#userstring) property determines the background image for the slider thumb. + + ```dae + INSTANCE MENUITEM_AUDIO_MUSICVOL_SLIDER(C_MENU_ITEM_DEF) + { + backPic = MENU_SLIDER_BACK_PIC; + type = MENU_ITEM_SLIDER; // Type: Slider + // [...] + onChgSetOption = "musicVolume"; // INI file parameter + onChgSetOptionSection = "SOUND"; // INI file section + userFloat[0] = 15; // Number of slider positions + userString[0] = MENU_SLIDER_POS_PIC; // Background image of the slider + // [...] + }; + ``` + +- `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]`](#userstring) property determines which image will be used for the disabled button. The [backPic](#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]`](#userstring) property determines which task list will be displayed in this element. + + ```dae + userstring[0] = "CURRENTMISSIONS"; + userstring[0] = "OLDMISSIONS"; + userstring[0] = "FAILEDMISSIONS"; + userstring[0] = "LOG"; + ``` + +### onSelAction +Array of commands executed when selecting the menu item. + +Each command receives parameters in the [`onSelAction_S`](#onselaction_s) property. + +Constants are described in the file [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L8-L15). + +```dae +CONST INT SEL_ACTION_UNDEF = 0; // No action. Used when setting game parameters, calling functions... +CONST INT SEL_ACTION_BACK = 1; // Return to the previous menu or game +CONST INT SEL_ACTION_STARTMENU = 2; // Open a menu +CONST INT SEL_ACTION_STARTITEM = 3; // Special command for save slots +CONST INT SEL_ACTION_CLOSE = 4; // Close menu or game +CONST INT SEL_ACTION_CONCOMMANDS = 5; // Execute console command +CONST INT SEL_ACTION_PLAY_SOUND = 6; // Play sound from C_SFX instance +CONST INT SEL_ACTION_EXECCOMMANDS = 7; // Execute command specified in the onSelAction_S field using RUN or EFFECT commands +``` + +### onSelAction_S +Arguments for commands specified in the [`onSelAction`](#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. + + ```dae + instance MENUITEM_MAIN_CREDITS(C_MENU_ITEM_DEF) + { + text[0] = "Credits"; + // [...] + onselaction[0] = SEL_ACTION_UNDEF; + oneventaction[1] = showcredits; + }; + + func int showcredits() + { + PlayVideo("credits.bik"); + PlayVideo("credits2.bik"); + return 1; + }; + ``` + +- `SEL_ACTION_BACK` + This command has no arguments. It returns to the previous menu or the game. + + ```dae + instance MENUITEM_MAIN_RESUME(C_MENU_ITEM_DEF) + { + text[0] = "Resume"; + text[1] = "Resume the current game"; + // [...] + onselaction[0] = SEL_ACTION_BACK; + }; + ``` + +- `SEL_ACTION_STARTMENU` + The argument for this command is the menu instance. The specified menu will be displayed. + + ```dae + instance MENUITEM_MAIN_EXIT(C_MENU_ITEM_DEF) + { + text[0] = "Quit Game"; + text[1] = "Leave the world of Gothic II"; + onselaction[0] = SEL_ACTION_STARTMENU; + onselaction_s[0] = "MENU_LEAVE_GAME"; + // [...] + }; + + instance MENU_LEAVE_GAME(C_MENU_DEF) + { + // [...] + }; + ``` + +- `SEL_ACTION_STARTITEM` + The argument is an interface element serving as a slot for saving the game. + + ```dae + INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF) + { + // [...] + onSelAction[0] = SEL_ACTION_STARTITEM; + onSelAction_S[0]= "MENUITEM_SAVE_SLOT1"; + onSelAction[1] = SEL_ACTION_CLOSE; + onSelAction_S[1]= "SAVEGAME_SAVE"; + }; + ``` + +- `SEL_ACTION_CLOSE` + The closing menu command supports the following arguments: + + - `NEW_GAME` + Start a new game. + + ```dae + instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) + { + // [...] + text[0] = "New Game"; + text[1] = "Start a new adventure"; + onSelAction[0] = SEL_ACTION_CLOSE; + onSelAction_S[0]= "NEW_GAME"; + }; + ``` + + - `LEAVE_GAME` + Exit the game. + + ```dae + INSTANCE MENUITEM_LEAVE_GAME_YES(C_MENU_ITEM_DEF) + { + // [...] + text[0] = "Yes."; + text[1] = "Yes, I'll be back!"; + onSelAction[0] = SEL_ACTION_CLOSE; + onSelAction_S[0]= "LEAVE_GAME"; + }; + ``` + + - `SAVEGAME_SAVE` + Save the game to the selected slot and return to the game. + + ```dae + INSTANCE MENUITEM_SAVE_SLOT1(C_MENU_ITEM_DEF) + { + // [...] + onSelAction[0] = SEL_ACTION_STARTITEM; + onSelAction_S[0]= "MENUITEM_SAVE_SLOT1"; + onSelAction[1] = SEL_ACTION_CLOSE; + onSelAction_S[1]= "SAVEGAME_SAVE"; + }; + ``` + + - `SAVEGAME_LOAD` + Load the game from the selected slot and return to the game. + + ```dae + INSTANCE MENUITEM_LOAD_SLOT1(C_MENU_ITEM_DEF) + { + // [...] + onSelAction[0] = SEL_ACTION_CLOSE; + onSelAction_S[0]= "SAVEGAME_LOAD"; + }; + ``` + +- `SEL_ACTION_CONCOMMANDS` + The argument is a console commands. + + ```dae + INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF) + { + // [...] + onSelAction[1] = SEL_ACTION_CONCOMMANDS; + onSelAction_S[1]= "goto pos 0 0 0"; + }; + ``` + +- `SEL_ACTION_PLAY_SOUND` + The argument is an C_SFX class instance. + + ```dae + INSTANCE MENUITEM_EXAMPLE_1(C_MENU_ITEM_DEF) + { + // [...] + onSelAction[1] = SEL_ACTION_PLAY_SOUND; + onSelAction_S[1]= "LevelUp"; + }; + ``` + +- `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. + + ```dae + INSTANCE MENU_ITEM_KEY_UP(C_MENU_ITEM_DEF) + { + // [...] + text[0] = "Forward"; + text[1] = "press DEL key to empty slot and RETURN to define"; + onSelAction[0] = SEL_ACTION_EXECCOMMANDS; + onSelAction_S[0]= "RUN MENU_ITEM_INP_UP"; + }; + + INSTANCE MENU_ITEM_INP_UP(C_MENU_ITEM_DEF) + { + // [...] + text[1] = "Please press the desired key for this action."; + type = MENU_ITEM_INPUT; + onChgSetOption = "keyUp"; + onChgSetOptionSection = "KEYS"; + }; + ``` + + - `EFFECTS` + Specifies the menu item instance to which the focus switches. + + ```dae + INSTANCE MENU_ITEM_SEL_MISSIONS_ACT(C_MENU_ITEM_DEF) + { + text[0] = "Current\nQuests"; + // [...] + onSelAction[0] = SEL_ACTION_EXECCOMMANDS; + onSelAction_S[0]= "EFFECTS MENU_ITEM_LIST_MISSIONS_ACT"; + }; + + instance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF) + { + type = MENU_ITEM_LISTBOX; + text[0] = "Act Missions"; + // [...] + userString[0] = "CURRENTMISSIONS"; + }; + ``` + + 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. + +### onChgSetOption + +Parameter of the `Gothic.ini` file that will be modified by this menu item. + +```dae +instance MENUITEM_GAME_FIGHTFOCUS_CHOICE(C_MENU_ITEM_DEF) +{ + text[0] = "none|box|lighten|both"; + // [...] + onChgSetOption = "highlightMeleeFocus"; // INI parameter + onChgSetOptionSection = "GAME"; // INI section + // [...] +}; +``` + +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. + +```ini +highlightMeleeFocus=2 +; ... here you can turn on an optional focus highlight effect during fighting +``` + +### onChgSetOptionSection +The section of the Gothic.ini file in which the parameter being changed is located. + +See [onChgSetOption](#onchgsetoption) above. + +### onEventAction +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`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L51-L59). + +```dae +const int EVENT_UNDEF = 0; // Undefined +const int EVENT_EXECUTE = 1; // Process start event +const int EVENT_CHANGED = 2; // Menu parameter change event +const int EVENT_LEAVE = 3; // Menu item focus loss event +const int EVENT_TIMER = 4; // Timer fire event +const int EVENT_CLOSE = 5; // Menu close event +const int EVENT_INIT = 6; // Initialization event +const int EVENT_SEL_PREV = 7; // Select event of the previous menu item +const int EVENT_SEL_NEXT = 8; // Select event of the next menu item +``` + +For example, you can use the function associated with the constant `EVENT_EXECUTE` to call a script function. + +```dae +instance MENUITEM_MAIN_INTRO(C_MENU_ITEM_DEF) +{ + text[0] = "Play Intro"; + text[1] = "Play introduction sequence"; + // [...] + onEventAction[EVENT_EXECUTE] = ShowIntro; +}; + +func int ShowIntro() +{ + PlayVideo("intro.bik"); + return 1; +}; +``` + +### posx +The horizontal position of the top left point of the menu on the screen, measured in virtual coordinates. + +!!! Example "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. + +### posy +The vertical position of the top left point of the menu on the screen, measured in virtual coordinates. + +### dimx +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. + +### dimy + +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. + +### sizeStartScale + +!!! Warning "Deprecated setting" + Size of the menu item at the beginning. + + +### flags +Flags of the menu item. + +Constants for all flags are described in the file [`Scripts/System/_intern/Menu.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Menu.d#L27-L41). + +```dae +const int IT_CHROMAKEYED = 1; +const int IT_TRANSPARENT = 2; +const int IT_SELECTABLE = 4; // Element can be selected +const int IT_MOVEABLE = 8; +const int IT_TXT_CENTER = 16; // Align text to center +const int IT_DISABLED = 32; // Interactive item +const int IT_FADE = 64; +const int IT_EFFECTS_NEXT = 128; // Flag for influencing an adjacent menu item +const int IT_ONLY_OUT_GAME = 256; // Element available only outside the game +const int IT_ONLY_IN_GAME = 512; // Element available only in-game +const int IT_PERF_OPTION = 1 << 10; // Option responsible for performance +const int IT_MULTILINE = 1 << 11; // Multi-line text element +const int IT_NEEDS_APPLY = 1 << 12; // Need to apply a settings. Used when changing screen resolution +const int IT_NEEDS_RESTART = 1 << 13; // The game need to be restarted +const int IT_EXTENDED_MENU = 1 << 14; // Advanced menu flag +``` + +- `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. + + ??? Example "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. + + ![type:video](https://www.youtube.com/embed/mfJag6fkfH8) + +- `IT_TXT_CENTER` + Aligns the text in the element to the center. + +- `IT_DISABLED` + The menu item becomes inactive. + + ```dae + instance MENUITEM_MAIN_NEWGAME(C_MENU_ITEM_DEF) + { + text[0] = "New Game"; + text[1] = "Start a new adventure"; + flags = flags | IT_TXT_CENTER | IT_DISABLED; + // [...] + }; + ``` + +- `IT_FADE` + Empty flag. Not used. + +- `IT_EFFECTS_NEXT` + This flag affects the next neighboring element, i.e., the element specified in the [`items`](./c_menu.md#items) list of the [`C_MENU`](./c_menu.md) class. + + ```dae + instance MENU_OPT_GAME(C_MENU_DEF) + { + // [...] + items[1] = "MENUITEM_GAME_SUB_TITLES"; + items[2] = "MENUITEM_GAME_SUB_TITLES_CHOICE"; + // [...] + }; + ``` + + In this case, the element affecting (MENUITEM_GAME_SUB_TITLES_CHOICE) is usually made non-selectable. + + ```dae + instance MENUITEM_GAME_SUB_TITLES(C_MENU_ITEM_DEF) + { + // [...] + text[0] = "Subtitles"; + text[1] = "Subtitles on/off"; + flags = flags | IT_EFFECTS_NEXT; + // [...] + }; + + instance MENUITEM_GAME_SUB_TITLES_CHOICE(C_MENU_ITEM_DEF) + { + // [...] + text[0] = "no|yes"; + flags = flags & ~IT_SELECTABLE; + // [...] + }; + ``` + + 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`. + +### openDelayTime + +!!! Warning "Deprecated setting" + Delay before opening a menu item. + +### openDuration + +!!! Warning "Deprecated setting" + The time the menu item was opened. + +### userFloat + +Numerical settings of the interface element. Depending on the interface element, the purpose of the property changes. See [type](#type). + +### userString + +String settings of the interface element. The purpose of the property changes depending on the interface element. See [type](#type)`. + +### frameSizeX + +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](#type) `MENU_ITEM_LISTBOX`. + +```dae +instance MENU_ITEM_LIST_MISSIONS_ACT(C_MENU_ITEM_DEF) +{ + backpic = "NW_Misc_CaveWall_01.tga"; + type = MENU_ITEM_LISTBOX; + text[0] = "Act Missions"; + // [...] + userstring[0] = "CURRENTMISSIONS"; + framesizex = 2000; + framesizey = 2000; +}; +``` + +As a result, we get the following frame (Source: [Gothic-Library](http://www.gothic-library.ru/publ/class_c_menu_item/1-1-0-37#frameSizeX)): + +![](../../../assets/images/c_menu_item_farmesize.png) + +And the width and height of the frame are set, as for all elements, by the [dimx](#dimx) and [dimy](#dimy) properties. + +### frameSizeY + +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](#framesizex) above. + + +### hideIfOptionSectionSet +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`](#hideifoptionset) and [`hideOnValue`](#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. + +```dae +instance MENU_ITEM_NEXTMENU(C_MENU_ITEM_DEF) +{ + text[0] = "More keys..."; + text[1] = "Configure further control keys"; + // [...] + hideifoptionsectionset = "GAME"; + hideifoptionset = "useGothic1Controls"; + hideonvalue = 1; +}; +``` + +!!! Tip + `Gothic.ini` settings can also be changed through the main menu. See [`onChgSetOption`](#onchgsetoption) and [`onChgSetOptionSection`](#onchgsetoptionsection). + +### hideIfOptionSet +The `Gothic.ini` file parameter, the value of which determines the display of this menu item. + +See [hideIfOptionSectionSet](#hideifoptionsectionset). + +### hideOnValue +The value of the `Gothic.ini` file parameter at which this interface element is not displayed. + +See [hideIfOptionSectionSet](#hideifoptionsectionset). + +## Predefined instances +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. | diff --git a/docs/zengin/scripts/classes/c_musicsys_cfg.md b/docs/zengin/scripts/classes/c_musicsys_cfg.md new file mode 100644 index 0000000000..a0d8fd84b6 --- /dev/null +++ b/docs/zengin/scripts/classes/c_musicsys_cfg.md @@ -0,0 +1,59 @@ +--- +title: C_MUSICSYS_CFG +--- + +# C_MUSICSYS_CFG Daedalus class + +!!! example "Acknowledgment" + Heavily inspired by the amazing documentation site [Gothic library](http://www.gothic-library.ru) + + +Class `C_MusicSys_CFG` defines the global settings for the game's music. + +An instance of this class is declared only once. +## Class definition +Class definition as it is defined in [`Scripts/System/_intern/Music.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Music.d#L40) script file. + +??? "C_MusicSys_CFG Daedalus class" + ```dae + class C_MusicSys_CFG + { + var float volume; // Music volume + var int bitResolution; // Sound quality + var int globalReverbEnabled; // Enable global reverb + var int sampleRate; // Frequency + var int numChannels; // Sound channels + var int reverbBufferSize; // Reverb buffer size + }; + ``` +## Class members + +| Variable | Type | Description | +|---------------------------------------------|--------|--------------------------------------------------------------| +| [volume](#volume) | float | Overall game music volume | +| [bitResolution](#bitresolution) | int | Sound quality | +| [globalReverbEnabled](#globalreverbenabled) | int | Enable global reverb | +| [sampleRate](#samplerate) | int | Frequency | +| [numChannels](#numchannels) | int | Number of sound chanells | +| [reverbBufferSize](#reverbbuffersize) | int | The size of reverb buffer | + +## Class member overview +Description of the class member variables. + +### volume +The overall volume of the background music (soundtrack). From 0.0 to 1.0. + +### bitResolution +Sound quality. 8 or 16 bit. + +### globalReverbEnabled +Enable global reverb. + +### sampleRate +Frequency. From 11050 to 44100. + +### numChannels +Number of sound channels. From 16 to 32. + +### reverbBufferSize +The size of the reverb buffer. \ No newline at end of file diff --git a/docs/zengin/scripts/classes/c_musictheme.md b/docs/zengin/scripts/classes/c_musictheme.md new file mode 100644 index 0000000000..ab04f13c8f --- /dev/null +++ b/docs/zengin/scripts/classes/c_musictheme.md @@ -0,0 +1,115 @@ +--- +title: C_MUSICTHEME +--- + +# C_MUSICTHEME Daedalus class + +!!! example "Acknowledgment" + Heavily inspired by the amazing documentation site [Gothic library](http://www.gothic-library.ru) + +Class `C_MusicTheme` describes musical themes. +## Class definition +Class definition as it is defined in [`Scripts/System/_intern/Music.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Music.d#L52) script file. + +??? "C_MusicTheme Daedalus class" + ```dae + class C_MusicTheme + { + var string file; // Sound file in DirectMusic `.sgt` format + var float vol; // Sound volume + var int loop; // Enable cycle + var float reverbMix; // Reverb mixing + var float reverbTime; // Reverb time + var int transType; // Type of transition to the next theme + var int transSubType; // Subtype of transition to the next theme song + }; + ``` +## Class members + +| Variable | Type | Description | +|-----------------------------------|--------|-------------------------------------------------------------------------------------| +| [file](#file) | string | Sound file in DirectMusic `.sgt` format | +| [vol](#vol) | float | Sound volume | +| [loop](#loop) | int | Enable/disable cycle | +| [reverbMix](#reverbmix) | float | Reverb mixing | +| [reverbTime](#reverbtime) | float | Reverb time | +| [transType](#transtype) | int | The type of transition to the next theme song | +| [transSubType](#transsubtype) | int | The subtype of transition to the next theme song | + +## Class member overview +Description of the class member variables. + +### file +DirectMusic sound in *.sgt format or MIDI file. + +### vol +The volume of the theme song. From 0.0 to 1.0. + +### loop +Enable/disable theme music looping. Disabled = 0. Enabled = 1. + +### reverbMix +Reverb mixing. Measured in decibels. + +### reverbTime +Reverberation time in milliseconds. + +### transType +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`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Music.d#L24) + +```dae +const int TRANSITION_TYPE_NONE = 1; // No transition +const int TRANSITION_TYPE_GROOVE = 2; // Ripple +const int TRANSITION_TYPE_FILL = 3; // Padding +const int TRANSITION_TYPE_BREAK = 4; // Break +const int TRANSITION_TYPE_INTRO = 5; // Introductory +const int TRANSITION_TYPE_END = 6; // End topic +const int TRANSITION_TYPE_ENDANDINTRO = 7; // End and start new +``` + +### transSubType +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`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/System/_intern/Music.d#L33) + +```dae +const INT TRANSITION_SUB_TYPE_IMMEDIATE = 1; // Instant transition +const INT TRANSITION_SUB_TYPE_BEAT = 2; // Rhythmic transition +const INT TRANSITION_SUB_TYPE_MEASURE = 3; // Gradual transition +``` + +## Name features +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. + +```dae +instance WOO_DAY_STD(C_MUSICTHEME_STANDARD) +{ + file = "woo_daystd.sgt"; +}; + +instance WOO_DAY_THR(C_MUSICTHEME_THREAT) +{ + file = "woo_daythr.sgt"; +}; + +instance WOO_DAY_FGT(C_MUSICTHEME_FIGHT) +{ + file = "woo_dayfgt.sgt"; +}; +``` +In addition, the suffix `_DAY_` and `_NGT_` determines whether the theme should be played on day or night. +```dae +instance OWD_DAY_FGT(C_MUSICTHEME_FIGHT) +{ + file = "owp_dayfgt.sgt"; +}; + +instance OWD_NGT_STD(C_MUSICTHEME_STANDARD) +{ + file = "owd_daystd.sgt"; +}; +``` +!!! Tip + In G2 the `C_MUSICTHEME_STANDARD`, `C_MUSICTHEME_THREAT` and `C_MUSICTHEME_FIGHT` prototypes are used by default. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/constants.md b/docs/zengin/scripts/extenders/ikarus/constants.md new file mode 100644 index 0000000000..26ffb254f4 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/constants.md @@ -0,0 +1,46 @@ +--- +title: Constants +--- + +# Ikarus User Constants + +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. + + +## MEM-Helper + +- `#!dae const string MEM_FARFARAWAY` + Waypoint where the Mem-Helper is spawned (default: `"TOT"`) +- `#!dae const string MEM_HELPER_NAME` + Name of the Mem-Helper (default: `"MEMHLP"`) + +## Debug + +- `#!dae const int zERR_ErrorBoxOnlyForFirst` + Controls whether only the first error should trigger an error box (default: `1`). +- `#!dae const int zERR_StackTraceOnlyForFirst` + Determines if stack traces should be displayed only for the first error (default: `0`). + +### MEM_Debug + +The [`MEM_Debug`](functions/debug.md#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: + +- `#!dae const string zERR_DEBUG_PREFIX` + Specifies a prefix to be added to each debug message (default: `"Debug: "`). +- `#!dae const int zERR_DEBUG_TOSPY` + Controls whether `MEM_Debug` messages should be sent to [zSpy](../../../tools/zSpy.md) (default: `1`). +- `#!dae const int zERR_DEBUG_TYPE` + Specifies the [message type](#error-message-types) for `MEM_Debug` messages when sent to [zSpy](../../../tools/zSpy.md) (default: `zERR_TYPE_INFO`). +- `#!dae const int zERR_DEBUG_TOSCREEN` + Determines whether `MEM_Debug` messages should be printed to the screen (default: `0`). +- `#!dae const int zERR_DEBUG_ERRORBOX` + Allows you to display an error box for `MEM_Debug` messages (default: `0`). + +### Error message types +```dae +const int zERR_TYPE_OK = 0; /* [ungenutzt] */ +const int zERR_TYPE_INFO = 1; /* MEM_Info */ +const int zERR_TYPE_WARN = 2; /* MEM_Warn */ +const int zERR_TYPE_FAULT = 3; /* MEM_Error */ +const int zERR_TYPE_FATAL = 4; /* [ungenutzt] */ +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/floats.md b/docs/zengin/scripts/extenders/ikarus/floats.md new file mode 100644 index 0000000000..d9fc9e25fd --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/floats.md @@ -0,0 +1,360 @@ +# Floats +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). + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: float.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/float.d) + +## Functions +!!! 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. + +### `mkf` +(make float) Converts the input integer x to a float value. +```dae +func int mkf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input integer + +**Return value** + +The function returns the float representation of the input integer x. + +### `truncf` +(truncate float) Truncates the decimal part of the input float x. +```dae +func int truncf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input float + +**Return value** + +The function returns the integer part of the input float x by discarding the decimal part. + +### `roundf` +(round float) Rounds the input float x to the nearest integer value. +```dae +func int roundf(var int x) +``` +**Parameters** + +- `#!dae 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. + +### `addf` +(add floats) Adds two ikarus floats together. +```dae +func int addf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae var int y` + The second float + +**Return value** + +The function returns the sum of the input floats `x` and `y`. (x + y) + +### `subf` +(subtract floats) Subtracts the second float from the first float. +```dae +func int subf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae 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) + +### `negf` +(negate float) Negates the input float. +```dae +func int negf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input float + +**Return value** + +The function returns the negation of the input float `x`. + +### `mulf` +(multiply floats) Multiplies two ikarus floats. +```dae +func int mulf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae var int y` + The second float + +**Return value** + +The function returns the product of multiplying the input floats x and y. (x * y) + +### `divf` +(divide floats) Divides two ikarus floats. +```dae +func int divf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The dividend float +- `#!dae var int y` + The divisor float + +**Return value** + +The function returns the quotient of dividing the input float x by y. (x / y) + +### `invf` +(inverse float) Computes the inverse of the input float. +```dae +func int invf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input float + +**Return value** + +The function returns the inverse of the `x`, calculated as `1/x`. + +### `gf` +(greater) Checks if the first float is greater than the second float. +```dae +func int gf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae var int y` + The second float + + + +**Return value** + +The function returns `TRUE` if `x` is greater than `y`, `FALSE` is returned otherwise. + +### `gef` +(greater or equal) Checks if the first float is greater than or equal to the second float. +```dae +func int gef(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae 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. + +### `lf` +(lower) Checks if the first float is less than the second float. +```dae +func int lf(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae var int y` + The second float + +**Return value** + +The function returns `TRUE` if `x` is less than `y`, `FALSE` is returned otherwise. + +### `lef` +(lower or equal) Checks if the first float is less than or equal to the second float. +```dae +func int lef(var int x, var int y) +``` +**Parameters** + +- `#!dae var int x` + The first float +- `#!dae 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. + +### `sqrf` +(square float) Calculates the square of the float. +```dae +func int sqrf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input float + +**Return value** + +The function returns the square of the input float `x`, computed as `x * x`. + +### `sqrtf` +(square root float) Calculates the square root of the float. +```dae +func int sqrtf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The input float + +**Return value** + +The function returns the square root of the input float `x`. + +### `sqrtf_approx` +Calculates the approximate square root of a float. +```dae +func int sqrtf_approx(var int f) +``` +**Parameters** + +- `#!dae var int f` + The input float + +**Return value** + +The function returns the approximate square root of the input float as an ikarus float. + +### `absf` +(absolute value) Computes the absolute value of a float. +```dae +func int absf(var int x) +``` +**Parameters** + +- `#!dae 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). + +### `fracf` +(fraction) Computes the fraction of two integers p and q. +```dae +func int fracf(var int p, var int q) +``` +**Parameters** + +- `#!dae var int p` + Numerator +- `#!dae var int q` + Denominator + +**Return value** + +The function returns the fraction of `p` divided by `q` as an ikarus float. + +### `castFromIntf` +Converts an ikarus float to a Daedalus float. +```dae +func float castFromIntf(var int f) +``` +**Parameters** + +- `#!dae var int f` + Ikarus float + +**Return Value** + +The function returns the value `f` as a Daedalus float. + +### `castToIntf` +Converts a Daedalus float to an ikarus float. +```dae +func int castToIntf(var float f) +``` +**Parameters** + +- `#!dae var float f` + Daedalus float + +**Return Value** + +The function returns the value `f` as an ikarus float. + +### `toStringf` +Converts a float value to its string representation. +```dae +func string toStringf(var int x) +``` +**Parameters** + +- `#!dae var int x` + Input float value + +**Return value** + +The function returns a string representation of the input float value. + +### `printf` +(print float) Prints the float on screen using `Print()`. +```dae +func void printf(var int x) +``` +**Parameters** + +- `#!dae var int x` + The printed float + +## Examples + +### Simple operations +```dae +var int float1; float1 = mkf(5); // Create an Ikarus float with value 5 +var int float2; float2 = mkf(2); // Create an Ikarus float with value 2 + +var int addResult; addResluts = addf(float1, float2); // Add float1 and float2 +var int subResult; subResults = subf(float1, float2); // Subtract float2 from float1 +var int mulResult; mulRelsults = mulf(float1, float2); // Multiply float1 by float2 +var int divResult; divResults = divf(float1, float2); // Divide float1 by float2 + +printf(addResult); // Output: 7 +printf(subResult); // Output: 3 +printf(mulResult); // Output: 10 +printf(divResult); // Output: 2.5 +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/arrays.md b/docs/zengin/scripts/extenders/ikarus/functions/arrays.md new file mode 100644 index 0000000000..fc91d9d9f1 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/arrays.md @@ -0,0 +1,227 @@ +# Arrays (zCArray) +Set of function for working with ZenGin's `zCArray` data structure. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L2017-L2338) + +## Functions + +### `MEM_ArrayCreate` +Creates an empty `zCArray` (allocates memory) and returns a pointer to it. +```dae +func int MEM_ArrayCreate() +``` +**Return value** + +The function returns a pointer to the created `zCArray`. + +### `MEM_ArrayFree` +Frees the memory allocated for a `zCArray` and its data. +```dae +func void MEM_ArrayFree(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` to be freed + +### `MEM_ArrayClear` +Clears the data of a `zCArray`, freeing the memory used by its elements. The array becomes empty. +```dae +func void MEM_ArrayClear (var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` to be cleared + +### `MEM_ArraySize` +Returns the size (number of elements) of an array. +```dae +func int MEM_ArraySize(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +**Return value** + +The function returns a number of a `zCArray` elements. + +### `MEM_ArrayWrite` +Writes a value at a specific position in the `zCArray`. +```dae +func void MEM_ArrayWrite(var int zCArray_ptr, var int pos, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int pos` + Position in the array where the value will be written +- `#!dae var int value` + Value to be written + +### `MEM_ArrayRead` +Reads the value at a specific position in the `zCArray`. +```dae +func int MEM_ArrayRead(var int zCArray_ptr, var int pos) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae 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`. + +### `MEM_ArrayInsert` +Appends a value to the end of the `zCArray`. The array is automatically resized if it is too small. +```dae +func void MEM_ArrayInsert (var int zCArray_ptr, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int value` + Value to be inserted + +### `MEM_ArrayPush` +Alias for [`MEM_ArrayInsert`](#mem_arrayinsert), inserts a value at the end of the `zCArray`. +```dae +func void MEM_ArrayPush (var int zCArray_ptr, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int value` + Value to be inserted + +### `MEM_ArrayPop` +Removes and returns the last element from the `zCArray`. +```dae +func int MEM_ArrayPop(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +**Return value** + +The function returns the element removed from the end of an array. + +### `MEM_ArrayTop` +Returns the last element of the `zCArray` without removing it. +```dae +func int MEM_ArrayTop(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +**Return value** + +The function returns the last element of an array. + +### `MEM_ArrayIndexOf` +Searches the `zCArray` for the first occurrence of a `value` and returns its index. +```dae +func int MEM_ArrayIndexOf(var int zCArray_ptr, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae 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. + +### `MEM_ArrayRemoveIndex` +Removes the element at a specific index from the `zCArray`. +```dae +func void MEM_ArrayRemoveIndex (var int zCArray_ptr, var int index) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int index` + Index of the element to be removed + +### `MEM_ArrayRemoveValue` +Removes all occurrences of a value from the `zCArray`. +```dae +func void MEM_ArrayRemoveValue (var int zCArray_ptr, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int value` + Value to be removed + +### `MEM_ArrayRemoveValueOnce` +Removes the first occurrence of a value from the `zCArray`. If value is not found, a warning is issued. +```dae +func void MEM_ArrayRemoveValueOnce (var int zCArray_ptr, var int value) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` +- `#!dae var int value` + Value to be removed + +### `MEM_ArraySort` +Sorts the elements of the `zCArray` in ascending order. +```dae +func void MEM_ArraySort(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +### `MEM_ArrayUnique` +Removes duplicate elements from the `zCArray`. +```dae +func void MEM_ArrayUnique(var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +### `MEM_ArrayToString` +Converts the `zCArray` to a string representation. +```dae +func string MEM_ArrayToString (var int zCArray_ptr) +``` +**Parameters** + +- `#!dae var int zCArray_ptr` + Pointer to the `zCArray` + +**Return value** + +The function returns a string representation of a given array. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/asm.md b/docs/zengin/scripts/extenders/ikarus/functions/asm.md new file mode 100644 index 0000000000..137db0caa3 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/asm.md @@ -0,0 +1,225 @@ +--- +title: ASM +--- +# Ikarus Machine Code Implementation (ASM) + +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](http://www.intel.com/products/processor/manuals/index.htm). + +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. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1064-L1267) + + +## Opcodes + +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](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1070-L1111) is a link to all instructions. + + +## Internal Stack + +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: + +### `ASMINT_Push` +Pushes the specified `data` onto the internal stack. +```dae +func void ASMINT_Push(var int data) +``` +**Parameters** + +- `#!dae var int data` + Data pushed onto internal stack + +### `ASMINT_Pop` +Pops and returns the topmost data from the internal stack. +```dae +func int ASMINT_Pop() +``` +**Return value** + +The function returns a data popped form the internal stack. + +## Functions (Core) + +The ASM core functionality provides a framework for assembling machine code instructions and executing them. The following functions are included: + +### `ASMINT_Init` +Initializes the ASM system by creating an internal stack and finding function addresses. +```dae +func void ASMINT_Init() +``` + +!!! Tip + It's worth noting that `ASMINT_Ini` is also invoked by the `MEM_InitAll` function. + +### `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`](#asm) or [`ASM_Here`](#ams_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. +```dae +func void ASM_Open(var int space) +``` +**Parameters** + +- `#!dae 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). + +```dae +const int ASM_StandardStreamLength = 256; +``` + +### `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. +```dae +func void ASM(var int data, var int length) +``` +**Parameters** + +- `#!dae var int data` + The machine code instruction or its part +- `#!dae var int length` + Length of the `data` (max 4 bytes) + + +=== "ASM_1" + ### `ASM_1` + [`ASM`](#asm) with `length` parameter hardcoded to 1. Writes one byte machine code instructions to the stream. + ```dae + func void ASM_1(var int data) + ``` + **Parameters** + + - `#!dae var int data` + One byte machine code instruction or its part + +=== "ASM_2" + ### `ASM_2` + [`ASM`](#asm) with `length` parameter hardcoded to 2. Writes two bytes machine code instructions to the stream. + ```dae + func void ASM_1(var int data) + ``` + **Parameters** + + - `#!dae var int data` + Two bytes machine code instruction or its part + +=== "ASM_3" + ### `ASM_3` + [`ASM`](#asm) with `length` parameter hardcoded to 3. Writes three bytes machine code instructions to the stream. + ```dae + func void ASM_1(var int data) + ``` + **Parameters** + + - `#!dae var int data` + Three bytes machine code instruction or its part + +=== "ASM_4" + ### `ASM_4` + [`ASM`](#asm) with `length` parameter hardcoded to 4. Writes four bytes machine code instructions to the stream. + ```dae + func void ASM_1(var int data) + ``` + **Parameters** + + - `#!dae var int data` + Four bytes machine code instruction or its part + +### `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`](#asm). It is guaranteed that the location where the code is written is also the location where it will be executed. +```dae +func int ASM_Here() +``` + +**Return value** + +The function returns an address that is the current position in the machine code stream. + +### `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`](mem_utility.md#mem_free) to avoid memory leaks. It is probably sufficient for almost all practical purposes. +```dae +func int ASM_Close() +``` +**Return value** + +The function returns a starting address of the stream (pointer to the stream). + + +### `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. +```dae +func void ASM_Run(var int ptr) +``` +**Parameters** + +- `#!dae var int ptr` + Pointer to the executed code (returned form [`ASM_Close`](#asm_close)) + +### `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. +```dae +func void ASM_RunOnce() +``` + +## Example +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. +```dae +func void SetAsPlayer(var C_NPC slf) { /* Address of the function */ + const int oCNpc__SetAsPlayer = 7612064; //0x7426A0 (Gothic2.exe) + + var int slfPtr; + slfPtr = MEM_InstToPtr (slf); + + //mov ecx slfPtr + ASM_1(ASMINT_OP_movImToECX); /* move a value to ecx */ + ASM_4(slfPtr); /* a value */ + + //call oCNpc__SetAsPlayer + ASM_1(ASMINT_OP_call); + ASM_4(oCNpc__SetAsPlayer - ASM_Here() - 4); + + ASM_RunOnce(); /* return will be added automatically */ +}; +``` + +!!! 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](call.md) that can be also used to implement `SetAsPlayer`. +```dae +func void SetAsPlayer(var C_NPC slf) { + const int oCNpc__SetAsPlayer = 7612064; + CALL__thiscall(MEM_InstToPtr(slf), oCNpc__SetAsPlayer); +}; +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/call.md b/docs/zengin/scripts/extenders/ikarus/functions/call.md new file mode 100644 index 0000000000..abf742c1af --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/call.md @@ -0,0 +1,409 @@ +# CALL Package +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)](asm.md) is part of the CALL package, but due to its complexity, this functionality is discussed in a separate article. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1268-L1654) + +## Call modes +There are two modes: + +### Disposable +The simple mode that produces a disposable call that is used only once. All parameters are hardcoded. + +```dae +func int hero_GetAssessEnemy() { + const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400 + + CALL_IntParam(_@(PERC_ASSESSENEMY)); + CALL_PutRetValTo(_@(funcID)); + CALL__thiscall(_@(hero), oCNpc__GetPerceptionFunc); + + var int funcID; + return +funcID; +}; +``` + +### Recyclable +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. + +```dae +func int Npc_GetPercFunc(var C_Npc npc, var int type) { + const int oCNpc__GetPerceptionFunc = 7726080; //0x75E400 + + var int npcPtr; npcPtr = _@(npc); + + const int call = 0; + if (CALL_Begin(call)) { + CALL_IntParam(_@(type)); + CALL_PutRetValTo(_@(funcID)); + CALL__thiscall(_@(npcPtr), oCNpc__GetPerceptionFunc); + call = CALL_End(); + }; + + var int funcID; + return +funcID; +}; +``` +> 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: + +## Start and End + +### `CALL_Open` +Initializes a Recyclable call mode. +```dae +func void CALL_Open() +``` + +### `CALL_Begin` +A practical wrapper for `CALL_Open`. Makes a call if it had been already created, initializes it otherwise. +```dae +func int CALL_Begin(var int ptr) +``` +**Parameters** + +- `#!dae 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. + +### `CALL_Close` +Finalizes a function call in recyclable mode, restoring the previous execution context. +```dae +func int CALL_Close() +``` + +### `CALL_End` +Finalizes a function call, pushes the pointer onto the stack, and runs the associated assembly code (makes an actual call). +```dae +func int CALL_End() +``` + +**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. + + + +## Passing parameters + +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. + +### `CALL_IntParam` +Passes an integer (`int32`) as a parameter to the called function. +```dae +func void CALL_IntParam(var int param) +``` +**Parameters** + +- `#!dae var int param` + Address of an integer to be passed + +### `CALL_FloatParam` +Passes an IEEE 7554 floating-point number (`single` / `zREAL`) as a parameter to the called function. +```dae +func void CALL_FloatParam(var int param) +``` +**Parameters** + +- `#!dae var int param` + Address of a float to be passed + +### `CALL_PtrParam` +Passes a pointer (`void*`) as a parameter to the called function. +```dae +func void CALL_PtrParam(var int param) +``` +**Parameters** + +- `#!dae var int param` + Pointer to be passed + +### `CALL_zStringPtrParam` +Passes a string (`zString*`) as a parameter to the called function. +```dae +func void CALL_zStringPtrParam(var string param) +``` +**Parameters** + +- `#!dae var string param` + String to be passed + +!!! Warning + This function only works when writing a disposable call! + +### `CALL_cStringPtrParam` +Passes a char array (`char **`) as a parameter to the called function. +```dae +func void CALL_cStringPtrParam(var string param) +``` +**Parameters** + +- `#!dae var string param` + String to be passed as character array` + +!!! Warning + This function only works when writing a disposable call! + +### `CALL_StructParam` +Passes a structure (struct) as a parameter to the called function. +```dae +func void CALL_StructParam(var int ptr, var int words) +``` +**Parameters** + +- `#!dae var int param` + Pointer to the object +- `#!dae 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. + +## The call +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. + +### `CALL__stdcall` +Calls a function with [`__stdcall`](https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170) (Standard Call) calling convention. +```dae +func void CALL__stdcall(var int adr) +``` +**Parameters** + +- `#!dae var int adr` + Address of a function + +### `CALL__thiscall` +Calls a function with [`__thiscall`](https://learn.microsoft.com/en-us/cpp/cpp/thiscall?view=msvc-170) calling convention. Used with a member functions. +```dae +func void CALL__thiscall(var int this, var int adr) +``` +**Parameters** + +- `#!dae var int this` + Pointer to the owner class object passed as a `this` parameter +- `#!dae var int adr` + Address of a function + +### `CALL__cdecl` +Calls a function with [`__cdecl`](https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170) calling convention. Used with non-Windows API and non-class functions. +```dae +func void CALL__cdecl (var int adr) +``` +**Parameters** + +- `#!dae var int adr` + Address of a function + + +### `CALL__fastcall` +Calls a function with [`__fastcall`](https://learn.microsoft.com/en-us/cpp/cpp/fastcall?view=msvc-170) calling convention. +```dae +func void CALL__fastcall(var int ecx, var int edx, var int adr) +``` +**Parameters** + +- `#!dae var int ecx` + First parameter of a function +- `#!dae var int edx` + Second parameter of a function +- `#!dae var int adr` + Address of a function + +## Return Value +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_retvalisfloat), [`CALL_RetValIszString`](#call_retvaliszstring), [`CALL_RetValIsStruct`](#call_retvalisstruct). + +### `CALL_PutRetValTo` +Simply places the return value to the given address (mostly the address of a daedalus integer). Must be called before [The Call](#the-call) function. +```dae +func void CALL_PutRetValTo(var int adr) +``` +**Parameters** + +- `#!dae var int adr` + Destination address of the return value + + +### `CALL_RetValAsInt` +Retrieves an integer returned by the called function. +```dae +func int CALL_RetValAsInt() +``` +**Return value** + +The function returns an integer returned by the previously called engine function. + +### `CALL_RetValIsFloat` +Specifies that the return value is a float. Must be called before [The Call](#the-call) function to allow getting the return value with [`CALL_RetValAsFloat`](#call_retvalasfloat). +```dae +func void CALL_RetValIsFloat() +``` + +### `CALL_RetValAsFloat` +Retrieves a float returned by the called function. +```dae +func int CALL_RetValAsFloat() +``` +**Return value** + +The function returns a float returned by the previously called engine function. + +### `CALL_RetValAsPtr` +Retrieves a pointer (`void*`) returned by the called function. +```dae +func int CALL_RetValAsPtr() +``` +**Return value** + +The function returns a pointer returned by the previously called engine function. + +### `CALL_RetValIsStruct` +Specifies that the return value is a Structure. Must be called before [The Call](#the-call) function to allow getting the return value with [`CALL_RetValAsStructPtr`](#call_retvalasstructptr). +```dae +func void CALL_RetValIsStruct(var int size) +``` +**Parameters** + +- `#!dae 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. + + +### `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`. +```dae +func MEMINT_HelperClass CALL_RetValAsStructPtr() +``` +**Return value** + +The function returns an instance returned by the previously called engine function. + +### `CALL_RetValIszString` +Specifies that the return value is a `zString` (20 bytes structure). Must be called before [The Call](#the-call) function to allow getting the return value with [`CALL_RetValAszStringPtr`](#call_retvalasstructptr) and [`CALL_RetValAszString`](#call_retvalaszstring). +```dae +func string CALL_RetValAszString() +``` + +!!! 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. + +### `CALL_RetValAszStringPtr` +Retrieves a `zString` pointer and converts it to the daedalus string. (don't frees the memory) +```dae +func string CALL_RetValAszStringPtr() +``` +**Return value** + +The function returns a daedalus string form a `zString` returned by the previously called engine function. + + +### `CALL_RetValAszString` +Retrieves a `zString` pointer and converts it to the daedalus string. (frees the memory) +```dae +func string CALL_RetValAszString() +``` +**Return value** + +The function returns a daedalus string form a `zString` returned by the previously called engine function. + +??? Trivia "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. + +## Examples + +### Apply overlay (Disposable) +```dae +// .text:0072D2C0:int __thiscall oCNpc::ApplyOverlay(class zSTRING const &) + +func void example1(){ + const int oCNpc__ApplyOverlay = 7525056; //0x72D2C0 (G2A) + CALL_zStringPtrParam ("HUMANS_MILITIA.MDS"); + CALL__thiscall (MEM_InstToPtr (hero), oCNpc__ApplyOverlay); + //We are not interested in the return value here. +}; +``` + +### Get time as string (Disposable) +e.g. `"7:30"` for half past seven in the morning +```dae +// .text:00780EC0:class zSTRING __thiscall oCWorldTimer::GetTimeString(void) + +func void example2(){ + const int oCWorldTimer__GetTimeString = 7868096; //780EC0 (G2A) + CALL_RetValIszString(); + CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer), oCWorldTimer__GetTimeString ); + PrintDebug (CALL_RetValAszString()); +}; +``` + +### Get the "sky time" (Disposable) +Sky time is a floating point value between 0 and 1 that jumps back from 1 to 0 at noon. +```dae +// .text:00781240:float __thiscall oCWorldTimer::GetSkyTime(void) + +func int GetSkyTime() { + const int oCWorldTimer__GetSkyTime = 7868992; //0x781240 + CALL_RetValIsFloat(); + CALL__thiscall (MEM_InstToPtr (MEM_WorldTimer), + oCWorldTimer__GetSkyTime); + + return CALL_RetValAsFloat(); +}; +``` + +### Delete Vob (Recyclable) +Call of the `oCWorld.RemoveVob`. [`MEM_DeleteVob`](objects.md#mem_deletevob) is an ikarus built-in function. +```dae +func void MEM_DeleteVob(var int vobPtr) { + var int world; world = MEM_Game._zCSession_world; + + const int call = 0; + if (CALL_Begin(call)) { + /* oCWorld.RemoveVob */ + CALL_IntParam(_@(vobPtr)); + CALL__thiscall(_@(world), MEMINT_SwitchG1G2(7171824, 7864512)); + + call = CALL_End(); + }; +}; +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/debug.md b/docs/zengin/scripts/extenders/ikarus/functions/debug.md new file mode 100644 index 0000000000..c12b920418 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/debug.md @@ -0,0 +1,139 @@ +# Debug +A set of debugging and error-handling functions for mod development with Ikarus. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L135-L327) + +## Functions + +### `MEM_CheckVersion` +Checks if the version of Ikarus is the specified version or newer. +```dae +func int MEM_CheckVersion(var int base, var int major, var int minor) +``` +**Parameters** + +- `#!dae var int base` + Base version number +- `#!dae var int major` + Major revision number +- `#!dae 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. + + +### `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](../../../../tools/zSpy.md) +```dae +func void MEM_SetShowDebug(var int on) +``` +**Parameters** + +- `#!dae var int on` + Specifies whether to turn on (`TRUE`) or off (`FALSE`) debug information. + +### `MEM_SendToSpy` +Sends a message to the debugging console. +```dae +func void MEM_SendToSpy(var int errorType, var string text) +``` +**Parameters** + +- `#!dae var int errorType` + Type of error (e.g., `zERR_TYPE_FAULT`, `zERR_TYPE_WARN`, `zERR_TYPE_INFO`) +- `#!dae var string text` + The message to be sent. + +### `MEM_ErrorBox` +Displays an error message in a message box. +```dae +func void MEM_ErrorBox(var string text) +``` +**Parameters** + +- `#!dae var string text` + The error message to be displayed. + +### `MEM_PrintStackTrace` +Prints the stack trace. +```dae +func void MEM_PrintStackTrace() +``` + +### `MEM_Error` +Handles a fatal error, displaying the error message and printing the stack trace. +```dae +func void MEM_Error(var string error) +``` +**Parameters** + +- `#!dae var string error` + The error message. + +### `MEM_Warn` +Handles a warning, displaying the warning message and printing the stack trace. +```dae +func void MEM_Warn(var string warn) +``` +**Parameters** + +- `#!dae var string warn` + The warning message. + +### `MEM_Info` +Handles an information message, printing it if enabled in the settings. +```dae +func void MEM_Info(var string info) +``` +**Parameters** + +- `#!dae var string info` + The information message. + +### `MEM_AssertFail` +Handles an assertion failure, reporting the error message as a fatal error. +```dae +func void MEM_AssertFail(var string assertFailText) +``` +**Parameters** + +- `#!dae var string assertFailText` + The assertion failure message. + +### `MEM_Debug` +Freely configurable debug channel. See how to setup it in the [Constants](../constants.md#mem_debug) article. +```dae +func void MEM_Debug(var string message) +``` +**Parameters** + +- `#!dae var string message` + The debug message. + +### `MEMINT_SwitchG1G2` +Switches between values based on the game version. Used mainly to change addresses in multi-platform hooks or function calls. +```dae +func int MEMINT_SwitchG1G2(var int g1Val, var int g2Val) +``` +**Parameters** + +- `#!dae var int g1Val` + The value to return if the game version is Gothic 1. +- `#!dae 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. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/ini_access.md b/docs/zengin/scripts/extenders/ikarus/functions/ini_access.md index 2821037b19..04e115bdbc 100644 --- a/docs/zengin/scripts/extenders/ikarus/functions/ini_access.md +++ b/docs/zengin/scripts/extenders/ikarus/functions/ini_access.md @@ -18,6 +18,17 @@ MEM_InitAll(); ## Read functions +### `MEM_GetCommandLine` +Returns the contents of the command line passed to Gothic. +```dae +func string MEM_GetCommandLine() +``` +**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"` + ### `MEM_GetGothOpt` Searches the `Gothic.ini` for an option. ```dae diff --git a/docs/zengin/scripts/extenders/ikarus/functions/ini_access.pl.md b/docs/zengin/scripts/extenders/ikarus/functions/ini_access.pl.md index c3ec2b5138..92b42c74cd 100644 --- a/docs/zengin/scripts/extenders/ikarus/functions/ini_access.pl.md +++ b/docs/zengin/scripts/extenders/ikarus/functions/ini_access.pl.md @@ -1,3 +1,6 @@ +--- +title: Ini File Access +--- # Dostęp do plików konfiguracyjnych Ta część Ikarusa umożliwia dostęp do `Gothic.ini` i pliku konfiguracyjnego załadowanej modyfikacji. @@ -15,6 +18,17 @@ MEM_InitAll(); ## Funkcje odczytu +### `MEM_GetCommandLine` +Zwraca zawartość linii poleceń przekazaną do Gothica. +```dae +func string MEM_GetCommandLine() +``` +**Zwracana wartość** + +Funkcja zwraca zawartość linii poleceń przekazaną do Gothica. Może to wyglądać na przykład tak: + +`"-TIME:7:35 -GAME:TEST_IKARUS.INI -ZREPARSE -ZWINDOW -ZLOG:5,S -DEVMODE -ZMAXFRAMERATE:30"` + ### `MEM_GetGothOpt` Przeszukuje `Gothic.ini` w poszukiwaniu opcji ```dae @@ -29,7 +43,7 @@ func string MEM_GetGothOpt(var string sectionname, var string optionname) **Zwracana wartość** -Funkcja zwraca wartość opcji w postaci łańcucha znaków, albo pustą zmienną, gdy opcja nie istnieje w danej sekcji. +Funkcja zwraca wartość opcji w postaci ciągu znaków, albo pustą zmienną, gdy opcja nie istnieje w danej sekcji. ### `MEM_GetModOpt` Przeszukuje ini załadowanej modyfikacji w poszukiwaniu opcji. @@ -45,7 +59,7 @@ func void MEM_GetModOpt(var string sectionname, var string optionname) **Zwracana wartość** -Funkcja zwraca wartość opcji w postaci łańcucha znaków, albo pustą zmienną, gdy opcja nie istnieje w danej sekcji. +Funkcja zwraca wartość opcji w postaci ciągu znaków, albo pustą zmienną, gdy opcja nie istnieje w danej sekcji. ### `MEM_GothOptSectionExists` Sprawdza, czy dana sekcja istnieje w `Gothic.ini` @@ -178,7 +192,7 @@ func void MEM_SetKeys(var string name, var int primary, var int secondary) - `#!dae var int primary` Podstawowy klawisz do przypisania, można go pobrać z pliku [Ikarus_Const_G1](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G1.d) / [Ikarus_Const_G2](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G2.d). - `#!dae var int secondary` - Zapasowy klawisz do przypisania, można go pobrać z pliku[Ikarus_Const_G1](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G1.d) / [Ikarus_Const_G2](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G2.d). + Zapasowy klawisz do przypisania, można go pobrać z pliku [Ikarus_Const_G1](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G1.d) / [Ikarus_Const_G2](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G2.d). ### `MEM_SetKey` Ustawia podstawowy klawisz klawiatury dla klawisza logicznego. diff --git a/docs/zengin/scripts/extenders/ikarus/functions/jumps_loops.md b/docs/zengin/scripts/extenders/ikarus/functions/jumps_loops.md new file mode 100644 index 0000000000..abb34e0d59 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/jumps_loops.md @@ -0,0 +1,458 @@ +# Jumps and Loops + +## Jumps + +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. + +### Initialization + +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. + +```dae +func void MEM_InitLabels() +``` +!!! Tip + It's worth noting that `MEM_InitLabels` is also invoked by the `MEM_InitAll` function. + +### Usage +- **Label Initialization** + Before attempting a jump, it's important to initialize the label to which the jump is intended. Forward jumps, where the jump point is encountered before the jump target, can be challenging. Label initialization looks like that: + ```dae + // [...] + var int label; + label = MEM_StackPos.position; + // [...] + ``` +- **Actual jump** + After initializing the label you could simply jump to it by setting `MEM_StackPos.position` to the label. + ```dae + // [...] + MEM_StackPos.position = label; + // [...] + ``` + +**Jump flowchart** + ```mermaid + flowchart TD + A(Start) --> B["var int label; \n label = MEM_StackPos.position;"]; + B --> C{Your code} + C -->D["MEM_StackPos.position = label;"]; + C --> E(End) + D --> |Jump| B; + ``` +### Notes and warnings + +- **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. + + +### Examples + +=== "Simple jump 'loop'" + The following code outputs the numbers from 0 to 42: + + ```dae + func void foo() { + /* Initialization */ + MEM_InitLabels(); + var int count; count = 0; + + /* Record the execution position in label. */ + var int label; + label = MEM_StackPos.position; + /* <---- label now points here, + * i.e. to the position AFTER the assignment of label. */ + + Print (ConcatStrings ("COUNT: ", IntToString (count))); + count += 1; + + if (count <= 42) { + /* Replace the execution position, + * with the "<-----" the system then continues */ + MEM_StackPos.position = label; + }; + + /* Once 43 is reached, the “loop” is exited. */ + }; + ``` +=== "Nested jump 'loop'" + The following code should enumerate all pairs (x,y) with `0 <= x < max_x`, `0 <= y < max_y` + ```dae + func void printpairs(var int max_x, var int max_y) + { + // Initialize labels + MEM_InitLabels(); + // PrintDebug should be used, i.e. activate debug output + MEM_SetShowDebug (1); + + var int x; var int y; x = 0; + + // while (x < max_x) + var int x_loop; x_loop = MEM_StackPos.position; + if (x < max_x) + { + y = 0; + // while (y < max_y) + var int y_loop; y_loop = MEM_StackPos.position; + if (y < max_y) + { + var string out; out = "("; + out = ConcatStrings (out, IntToString (x)); + out = ConcatStrings (out, ", "); + out = ConcatStrings (out, IntToString (y)); + out = ConcatStrings (out, ")"); + PrintDebug (out); + y += 1; + + // continue y_loop + MEM_StackPos.position = y_loop; + }; + x += 1; + // continue x_loop + MEM_StackPos.position = x_loop; + }; + }; + + /* + Output of a call printpairs(4,2) would then be: + 00:36 Info: 5 U: Skript: (0, 0) .... + 00:36 Info: 5 U: Skript: (0, 1) .... + 00:36 Info: 5 U: Skript: (1, 0) .... + 00:36 Info: 5 U: Skript: (1, 1) .... + 00:36 Info: 5 U: Skript: (2, 0) .... + 00:36 Info: 5 U: Skript: (2, 1) .... + 00:36 Info: 5 U: Skript: (3, 0) .... + 00:36 Info: 5 U: Skript: (3, 1) .... + */ + ``` + +## Label and Goto + +Besides the normal [jumps](#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. + +### `MEM_Label` +Function that works like a `label = MEM_StackPos.position;`. You could jump to it with [`MEM_Goto`](#mem_goto). +```dae +func void MEM_Label(var int lbl) +``` +**Parameters** + +- `#!dae var int lbl` + Number of the label, used for nested loop or multiple loops within one function + +### `MEM_Goto` +Function that works like a `MEM_StackPos.position = label;`. Executes a jump to a [`MEM_Label`](#mem_label) with specified number. +```dae +func void MEM_Goto(var int lbl) +``` +**Parameters** + +- `#!dae var int lbl` + Number of the label, the function will jump to + +### Usage +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](#notes-and-warnings) of the Jumps is recommended. + +**Label-Goto loop flowchart** + ```mermaid + flowchart TD + A(Start) --> B["MEM_Label(0);"]; + B --> C{Your code} + C -->D["MEM_Goto(0);"]; + C --> E(End) + D --> |Jump| B; + ``` + +```dae title="Label-Goto loop" +func void LabelGoto_test() { + var int i; + MEM_Label(0); + MEM_Debug(IntToString(i)); + i = i + 1; + if(i >= 4) + { + return; + }; + MEM_Goto(0); +}; + +// Results: +// Info: 0 Q: Debug: 0 +// Info: 0 Q: Debug: 1 +// Info: 0 Q: Debug: 2 +// Info: 0 Q: Debug: 3 +``` + +### Examples + +=== "Simple Label-Goto 'loop'" + The following code outputs the numbers from 0 to 42: + + ```dae + func void foo() { + var int count; count = 0; + + MEM_Label(0); + /* <---- label now points here, + * i.e. to the position AFTER the assignment of label. */ + + Print (ConcatStrings ("COUNT: ", IntToString (count))); + count += 1; + + if (count <= 42) { + // Jump to the MEM_Label + MEM_Goto(0); + }; + + /* Once 43 is reached, the “loop” is exited. */ + }; + ``` +=== "Nested Label-Goto 'loop'" + The following code should enumerate all pairs (x,y) with `0 <= x < max_x`, `0 <= y < max_y` + ```dae + func void printpairs(var int max_x, var int max_y) + { + // PrintDebug should be used, i.e. activate debug output + MEM_SetShowDebug (1); + + var int x; var int y; x = 0; + + // while (x < max_x) + MEM_Label(0); + if (x < max_x) + { + y = 0; + // while (y < max_y) + MEM_Label(1); + if (y < max_y) + { + var string out; out = "("; + out = ConcatStrings (out, IntToString (x)); + out = ConcatStrings (out, ", "); + out = ConcatStrings (out, IntToString (y)); + out = ConcatStrings (out, ")"); + PrintDebug (out); + y += 1; + + MEM_Goto(1); + }; + x += 1; + MEM_Goto(0); + }; + }; + + /* + Output of a call printpairs(4,2) would then be: + 00:36 Info: 5 U: Skript: (0, 0) .... + 00:36 Info: 5 U: Skript: (0, 1) .... + 00:36 Info: 5 U: Skript: (1, 0) .... + 00:36 Info: 5 U: Skript: (1, 1) .... + 00:36 Info: 5 U: Skript: (2, 0) .... + 00:36 Info: 5 U: Skript: (2, 1) .... + 00:36 Info: 5 U: Skript: (3, 0) .... + 00:36 Info: 5 U: Skript: (3, 1) .... + */ + ``` + +## While loop + +Ikarus also implements a while loop. Its syntax isn't as good as the loop from [zParserExtender](../../zparserextender/syntax_extensions/while.md), due to the daedalus limitations, but it works as a normal while loop that can be found in many programming languages. + +### Syntax +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){`. +```dae +func void while(var int b) +``` + +- **end constant** +That works like an ending brace `}`. +```dae +const int end = -72; +``` + +- **break and continue constant** +These two constants works like a regular `break` and `continue` statements in C. +```dae +const int break = -42; +const int continue = -23; +``` + +```dae title="while loop" +func void while_test() { + var int value; value = 10; + while(value > 0); //{ + + if (value == 8) + { + continue; + }; + + if (value == 2) + { + break; + }; + end; //} +}; +``` + +### Examples + +=== "Simple while loop" + The following code outputs the numbers from 0 to 42: + + ```dae + func void foo() { + var int count; count = 0; + while(count <= 42); //{ + Print (ConcatStrings ("COUNT: ", IntToString (count))); + count += 1; + end; //} + + /* Once 43 is reached, the loop is exited. */ + }; + ``` +=== "Nested while loop" + The following code should enumerate all pairs (x,y) with `0 <= x < max_x`, `0 <= y < max_y` + ```dae + func void printpairs(var int max_x, var int max_y) + { + // PrintDebug should be used, i.e. activate debug output + MEM_SetShowDebug (1); + + var int x; var int y; x = 0; + + while(x < max_x); //{ + y = 0; + while(y < max_y); //{ + var string out; out = "("; + out = ConcatStrings (out, IntToString (x)); + out = ConcatStrings (out, ", "); + out = ConcatStrings (out, IntToString (y)); + out = ConcatStrings (out, ")"); + PrintDebug (out); + y += 1; + end; //} + x += 1; + end; //} + }; + + /* + Output of a call printpairs(4,2) would then be: + 00:36 Info: 5 U: Skript: (0, 0) .... + 00:36 Info: 5 U: Skript: (0, 1) .... + 00:36 Info: 5 U: Skript: (1, 0) .... + 00:36 Info: 5 U: Skript: (1, 1) .... + 00:36 Info: 5 U: Skript: (2, 0) .... + 00:36 Info: 5 U: Skript: (2, 1) .... + 00:36 Info: 5 U: Skript: (3, 0) .... + 00:36 Info: 5 U: Skript: (3, 1) .... + */ + ``` + +## Repeat loop + +In addition Ikarus implements something called **Repeat loop**. + +### Initialization + +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`. + +```dae +func void MEM_InitRepeat() +``` +!!! Tip + It's worth noting that `MEM_InitRepeat` is also invoked by the `MEM_InitAll` function. + + +### Syntax +Repeat loop has a syntax very similar to the [while loop](#syntax). 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: + +```dae +func void Repeat(var int variable, var int limit) +``` + +- `#!dae var int variable` + A variable that increase with every loop iteration. +- `#!dae var int limit` + A variable that defines the number of loop iterations. If `variable >= limit` the loop is exited. + +**Repeat loop flowchart** +```mermaid +flowchart TD + A(Start) --> B["Repeat(i, limit)"] + B --> C{i < limit} + C -->|true| D[Command] + D --> |i = i + 1| B + C --> |false| E(End) +``` + + +```dae title="Repeat loop" +func void Repeat_test() { + Repeat(i, 4); var int i; //{ + MEM_Debug(IntToString(i)); + end; //} +}; + +// Results: +// Info: 0 Q: Debug: 0 +// Info: 0 Q: Debug: 1 +// Info: 0 Q: Debug: 2 +// Info: 0 Q: Debug: 3 +``` + +### Examples + +=== "Simple Repeat loop" + The following code outputs the numbers from 0 to 42: + + ```dae + func void foo() { + Repeat(count, 43); var int count; //{ + Print (ConcatStrings ("COUNT: ", IntToString (count))); + end; //} + + /* Once 43 is reached, the loop is exited. */ + }; + ``` +=== "Nested Repeat loop" + The following code should enumerate all pairs (x,y) with `0 <= x < max_x`, `0 <= y < max_y` + ```dae + func void printpairs(var int max_x, var int max_y) + { + // PrintDebug should be used, i.e. activate debug output + MEM_SetShowDebug (1); + + var int x; var int y; x = 0; + + Repeat(x, max_x); //{ + y = 0; + Repeat(y, max_y); //{ + var string out; out = "("; + out = ConcatStrings (out, IntToString (x)); + out = ConcatStrings (out, ", "); + out = ConcatStrings (out, IntToString (y)); + out = ConcatStrings (out, ")"); + PrintDebug (out); + end; //} + end; //} + }; + + /* + Output of a call printpairs(4,2) would then be: + 00:36 Info: 5 U: Skript: (0, 0) .... + 00:36 Info: 5 U: Skript: (0, 1) .... + 00:36 Info: 5 U: Skript: (1, 0) .... + 00:36 Info: 5 U: Skript: (1, 1) .... + 00:36 Info: 5 U: Skript: (2, 0) .... + 00:36 Info: 5 U: Skript: (2, 1) .... + 00:36 Info: 5 U: Skript: (3, 0) .... + 00:36 Info: 5 U: Skript: (3, 1) .... + */ + ``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/keyboard.md b/docs/zengin/scripts/extenders/ikarus/functions/keyboard.md index 82f4d20d47..0239eb9318 100644 --- a/docs/zengin/scripts/extenders/ikarus/functions/keyboard.md +++ b/docs/zengin/scripts/extenders/ikarus/functions/keyboard.md @@ -4,6 +4,9 @@ title: Keyboard # Keyboard interaction This part of Ikarus implements function that make interaction with keyboard possible. +!!! Info + Keyboard interaction is also implemented with [gameKeyEvents.d](../../standalone/gameKeyEvents.md) + ## Initialization The best way to initialize all Ikarus functions is to call `MEM_InitAll()` in the `Init_Global()` initialization function. !!! warning @@ -14,11 +17,26 @@ MEM_InitAll(); ``` ## Implementation -[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L4198) +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L4198-L4292) ## Functions !!! 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](ini_access.md#key-functions). + +### `MEM_KeyPressed` +Checks if the key is hold right at the moment of function call. +```dae +func int MEM_KeyPressed(var int key) +``` +**Parameters** + +- `#!dae var int key` + Checked key + +**Return value** + +The function returns `TRUE` if the key is hold, `FALSE` is returned otherwise. + ### `MEM_KeyState` Returns the state of the `key`. ```dae diff --git a/docs/zengin/scripts/extenders/ikarus/functions/mem_access.md b/docs/zengin/scripts/extenders/ikarus/functions/mem_access.md index 07e248c476..717703ee01 100644 --- a/docs/zengin/scripts/extenders/ikarus/functions/mem_access.md +++ b/docs/zengin/scripts/extenders/ikarus/functions/mem_access.md @@ -82,7 +82,7 @@ The function returns integer value from the array if the address is correct. ### `MEM_ReadStringArray` !!! Info - `MEM_ReadStringArray` has been already moved to the LeGo PermMem package. + `MEM_ReadStringArray` has been already moved to the LeGo [PermMem](../../lego/tools/permmem.md#mem_readstringarray) package. ### `MEM_ReadByteArray` Reads byte from the array at the `arrayAddress`. @@ -114,7 +114,7 @@ func void MEM_WriteInt(var int address, var int value) - `#!dae var int value` Integer value to write -??? abstract "Examples" +??? abstract "Example" An example of using this function is the following Ikarus function, which turns debugging messages on and off: ```dae func void MEM_SetShowDebug(var int on) diff --git a/docs/zengin/scripts/extenders/ikarus/functions/mem_utility.md b/docs/zengin/scripts/extenders/ikarus/functions/mem_utility.md new file mode 100644 index 0000000000..22bc428e00 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/mem_utility.md @@ -0,0 +1,231 @@ +# Memory utility +Ikarus utility functions, for memory management and manipulation. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1655-L1838) + +## Functions + +### `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`](#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. +```dae +func int MEM_Alloc(var int amount) +``` +**Parameters** + +- `#!dae var int amount` + The amount of bytes to allocate + +**Return value** + +The function returns a pointer to the allocated memory area. + +### `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. +```dae +func int MEM_Realloc(var int ptr, var int oldsize, var int newsize) +``` +**Parameters** + +- `#!dae var int ptr` + The original pointer to the memory block +- `#!dae var int oldsize` + The size of the original memory block +- `#!dae var int newsize` + The size of the new memory block + +**Return value** + +The function returns a pointer to the modified memory area. + +### `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. +```dae +func void MEM_Free(var int ptr) +``` +**Parameters** + +- `#!dae var int ptr` + Pointer to the released memory block + +### `MEM_Copy` +Copies a specified number of words from the source address to the destination address. +```dae +func void MEM_Copy(var int src, var int dst, var int wordcount) +``` +**Parameters** + +- `#!dae var int src` + The source address to copy from +- `#!dae var int dst` + The destination address to copy to +- `#!dae var int wordCount` + The number of words to copy + +### `MEM_CopyWords` +Alias to [`MEM_Copy`](#mem_copy). Copies a specified number of words from the source address to the destination address. +```dae +func void MEM_CopyWords(var int src, var int dst, var int wordcount) +``` +**Parameters** + +- `#!dae var int src` + The source address to copy from +- `#!dae var int dst` + The destination address to copy to +- `#!dae var int wordCount` + The number of words to copy + +### `MEM_CopyBytes` +Copies a specified number of bytes from the source address to the destination address +```dae +func void MEM_CopyBytes(var int src, var int dst, var int byteCount) +``` +**Parameters** + +- `#!dae var int src` + The source address to copy from +- `#!dae var int dst` + The destination address to copy to +- `#!dae var int byteCount` + The number of bytes to copy + +### `MEM_Swap` +Swaps a specified number of words between the source address and the destination address. +```dae +func void MEM_Swap(var int src, var int dst, var int wordCount) +``` +**Parameters** + +- `#!dae var int src` + The source address to swap from +- `#!dae var int dst` + The destination address to swap to +- `#!dae var int wordCount` + The number of words to swap + +### `MEM_SwapWords` +Alias to [`MEM_Swap`](#mem_swap). Swaps a specified number of words between the source address and the destination address. +```dae +func void MEM_SwapWords(var int src, var int dst, var int wordCount) +``` +**Parameters** + +- `#!dae var int src` + The source address to swap from +- `#!dae var int dst` + The destination address to swap to +- `#!dae var int wordCount` + The number of words to swap + +### `MEM_SwapBytes` +Swaps a specified number of bytes between the source address and the destination address. +```dae +func void MEM_SwapBytes(var int src, var int dst, var int byteCount) +``` +**Parameters** + +- `#!dae var int src` + The source address to swap from +- `#!dae var int dst` + The destination address to swap to +- `#!dae var int byteCount` + The number of bytes to swap + + +### `MEM_Clear` +Sets a specified number of bytes in memory to zero. +```dae +func void MEM_Clear(var int ptr, var int size) +``` +**Parameters** + +- `#!dae var int ptr` + The memory address to start clearing from +- `#!dae var int size` + The number of bytes to clear + +### `MEM_Compare` +Compares a specified number of words between two memory blocks. +```dae +func int MEM_Compare(var int ptr0, var int ptr1, var int wordCount) +``` +**Parameters** + +- `#!dae var int ptr0` + The first memory block to compare +- `#!dae var int ptr1` + The second memory block to compare +- `#!dae 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. + + +### `MEM_CompareWords` +Alias to [`MEM_Compare`](#mem_compare). Compares a specified number of words between two memory blocks. +```dae +func int MEM_CompareWords(var int ptr0, var int ptr1, var int wordCount) +``` +**Parameters** + +- `#!dae var int ptr0` + The first memory block to compare +- `#!dae var int ptr1` + The second memory block to compare +- `#!dae 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. + +### `MEM_CompareBytes` +Compares a specified number of bytes between two memory blocks. +```dae +func int MEM_CompareBytes(var int ptr1, var int ptr2, var int byteCount) +``` +**Parameters** + +- `#!dae var int ptr0` + The first memory block to compare +- `#!dae var int ptr1` + The second memory block to compare +- `#!dae 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. diff --git a/docs/zengin/scripts/extenders/ikarus/functions/objects.md b/docs/zengin/scripts/extenders/ikarus/functions/objects.md new file mode 100644 index 0000000000..0b11fa1422 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/objects.md @@ -0,0 +1,301 @@ +# zCObjects + +Set of functions for working with `zCObject` and its subclasses instances. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L3755-L4197) + +## Global instances +Ikarus package introduces the following instances: + +```dae +instance MEM_Game (oCGame); +instance MEM_World(oWorld); +instance MEM_Timer(zCTimer); +instance MEM_WorldTimer(oCWorldTimer); +instance MEM_Vobtree(zCTree); +instance MEM_InfoMan(oCInfoManager); +instance MEM_InformationMan (oCInformationManager); +instance MEM_Waynet(zCWaynet); +instance MEM_Camera(zCCamera); +instance MEM_SkyController(zCSkyController_Outdoor); +instance MEM_SpawnManager (oCSpawnManager); +instance MEM_GameMananger (CGameManager); +instance MEM_GameManager (CGameManager); +instance MEM_Parser(zCParser); +``` + +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`](#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. + +### `MEM_InitGlobalInst` +Initializes global instances of commonly used objects in the game (is called by the `MEM_InitAll` function). +```dae +func void MEM_InitGlobalInst() +``` + +!!! 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`. + +## Functions + +??? Trivia "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. + + ```dae + class zCClassDef { + var string className; //zSTRING + var string baseClassName; //zSTRING + var string scriptClassName; //zSTRING + var int baseClassDef; //zCClassDef* + var int createNewInstance; //zCObject* ( *) (void) + var int createNewInstanceBackup; //zCObject* ( *) (void) + var int classFlags; //zDWORD + var int classSize; //zDWORD + var int numLivingObjects; + var int numCtorCalled; + var int hashTable; //zCObject** + var int objectList_array; //zCObject** + var int objectList_numAlloc; //int + var int objectList_numInArray; //int + var int bitfield; + }; + ``` + + Full Ikarus definition of this class, with members description can be found in [`Misc.d`](https://github.com/Lehona/Ikarus/blob/master/EngineClasses_G1/Misc.d#L490-L537) file. The class is same for G1 and G2A engines. + +### `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. + +```dae +func int MEM_GetClassDef(var int objPtr) +``` +**Parameters** + +- `#!dae 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. + +??? abstract "Example" + This would return a pointer to the `zCClassDef` object that belongs to the `oCNpc` class. + ```dae + func int example1 + { + var int her; her = MEM_InstToPtr(hero); + return MEM_GetClassDef(her); + }; + ``` + + +### `MEM_GetClassName` +This function returns the name of the class to which an object belongs. +```dae +func string MEM_GetClassName(var int objPtr) +``` +**Parameters** + +- `#!dae 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. + +??? abstract "Example" + This would return a name of the `oCNpc` class as a string. + ```dae + func string example2 + { + var int her; her = MEM_InstToPtr(hero); + return MEM_GetClassName(her); + }; + // return: "oCNpc" + ``` + +### `MEM_CheckInheritance` +Checks if an object is derived from a specific class definition. +```dae +func int MEM_CheckInheritance(var int objPtr, var int classDef) +``` +**Parameters** + +- `#!dae var int objPtr` + A pointer to the object to be checked +- `#!dae 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. + +#### `Hlp_Is_*` +In addition [`MEM_CheckInheritance`](#mem_checkinheritance) function has some overloads with hardcoded `classDef` parameter. + +```dae +func int Hlp_Is_oCMobFire(var int ptr){}; +func int Hlp_Is_zCMover(var int ptr){}; +func int Hlp_Is_oCMob(var int ptr){}; +func int Hlp_Is_oCMobInter(var int ptr){}; +func int Hlp_Is_oCMobLockable(var int ptr){}; +func int Hlp_Is_oCMobContainer(var int ptr){}; +func int Hlp_Is_oCMobDoor(var int ptr){}; +func int Hlp_Is_oCMobBed(var int ptr){}; +func int Hlp_Is_oCMobSwitch(var int ptr){}; +func int Hlp_Is_oCMobWheel(var int ptr){}; +func int Hlp_Is_oCMobLadder(var int ptr){}; +func int Hlp_Is_oCNpc(var int ptr){}; +func int Hlp_Is_oCItem(var int ptr){}; +func int Hlp_Is_zCVobLight(var int ptr){}; +``` + +The usage of these functions is probably obvious, they checks if the given object belongs to class given in the function name. + + +### `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`](../../../../worlds/Classes/zCVob.md)), if you don't need the additional properties. +```dae +func int MEM_InsertVob(var string vis, var string wp) +``` +**Parameters** + +- `#!dae 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.) +- `#!dae var string wp` + Name of the waypoint to insert Vob on + +**Return value** + +The function returns a pointer to the created object. + +### `MEM_DeleteVob` +Deletes a specific Vob form world. +```dae +func void MEM_DeleteVob(var int vobPtr) +``` +**Parameters** + +- `#!dae var int vobPtr` + Pointer to a [`zCVob`](../../../../worlds/Classes/zCVob.md) object to be deleted + +### `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. +```dae +func void MEM_RenameVob(var int vobPtr, var string newName) +``` +**Parameters** + +- `#!dae var int vobPtr` + Pointer to a [`zCVob`](../../../../worlds/Classes/zCVob.md) object to be renamed +- `#!dae var string newName` + The new Name of the Vob + +=== "MEM_TriggerVob" + + ### `MEM_TriggerVob` + Sends a trigger message to the Vob. + ```dae + func void MEM_TriggerVob(var int vobPtr) + ``` + **Parameters** + + - `#!dae var int vobPtr` + Pointer to a triggered [`zCVob`](../../../../worlds/Classes/zCVob.md) + + !!! 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. +=== "MEM_UntriggerVob" + + ### `MEM_UntriggerVob` + Sends an untrigger message to the Vob. + ```dae + func void MEM_TriggerVob(var int vobPtr) + ``` + **Parameters** + + - `#!dae var int vobPtr` + Pointer to an untriggered [`zCVob`](../../../../worlds/Classes/zCVob.md) + + !!! 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. + +### `MEM_SearchVobByName` +Returns the address of a [`zCVob`](../../../../worlds/Classes/zCVob.md) named `str` if such a Vob exists. +```dae +func int MEM_SearchVobByName(var string str) +``` +**Parameters** + +- `#!dae var string str` + Name of searched [`zCVob`](../../../../worlds/Classes/zCVob.md) + +**Return value** + +The function returns a pointer to the [`zCVob`](../../../../worlds/Classes/zCVob.md) if the object with the given name exist. `0` is returned otherwise. + + +### `MEM_SearchAllVobsByName` +Variation of [`MEM_SearchVobByName`](#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. +```dae +func int MEM_SearchAllVobsByName(var string str) +``` +**Parameters** + +- `#!dae var string str` + Name of searched [`zCVob`](../../../../worlds/Classes/zCVob.md) + +**Return value** + +The function returns a pointer to the created `zCArray`, that contains pointers to the all Vobs with the specified name. + +### `MEM_GetBufferCRC32` +Calculates the CRC32 hash value from a byte array starting at the address specified by `buf` and having a length of `buflen`. +```dae +func int MEM_GetBufferCRC32(var int buf, var int buflen) +``` +**Parameters** + +- `#!dae var int buf` + Address of a byte array, the hash calculation will begin from + +- `#!dae 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. + + +### `MEM_GetStringHash` +Calculates the CRC32 hash value for a string. +```dae +func int MEM_GetStringHash(var string str) +``` +**Parameters** + +- `#!dae 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. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/parser.md b/docs/zengin/scripts/extenders/ikarus/functions/parser.md new file mode 100644 index 0000000000..b0140fa9bb --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/parser.md @@ -0,0 +1,597 @@ +--- +title: Parser stuff +--- +# `zCParser` related functions +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. + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L513) + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +### `MEM_ReinitParser` +Parser operations are initialized with this function. +```dae +func void MEM_ReinitParser() +``` + +!!! Tip + It's worth noting that `MEM_ReinitParser` is also invoked by the `MEM_InitAll` function. + + +## Pointers and instances + +### `MEM_PtrToInst` +Returns an instance pointed to by the pointer. If the pointer is null an error is thrown. +```dae +func MEMINT_HelperClass MEM_PtrToInst(var int ptr) +``` +**Parameters** + +- `#!dae 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. + +```dae +func MEMINT_HelperClass _^ (var int ptr) +``` + +??? abstract "Example" + Following code + ```dae + var oCNpc her; her = MEM_PtrToInst(heroPtr); + ``` + is equivalent to + ```dae + var oCNpc her; her = _^(heroPtr); + ``` + + +### `MEM_NullToInst` +Returns an instance from a null pointer. +```dae +func MEMINT_HelperClass MEM_NullToInst() +``` + +### `MEM_AssignInst` +Takes an instance from a pointer and assigns it to a given instance. If the pointer is null an error is thrown. +```dae +func void MEM_AssignInst(var int inst, var int ptr) +``` +**Parameters** + +- `#!dae var int ptr` + Pointer to assign an instance from +- `#!dae var int inst` + Instance to which the pointer will be assigned + +??? abstract "Example" + Following code + ```dae + var oCNpc inst; + MEM_AssignInst (inst, ptr); + ``` + is equivalent to + ```dae + var oCNpc inst; + inst = MEM_PtrToInst(ptr); + ``` + +### `MEM_AssignInstNull` +Assigns null pointer to a given instance. +```dae +func void MEM_AssignInstNull(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + Instance to which the null pointer will be assigned + +### `MEM_InstToPtr` +Returns a pointer to given instance. +```dae +func int MEM_InstToPtr(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + The instance to which the pointer is returned + +### `MEM_InstGetOffset` +Alias to `MEM_InstToPtr`. Returns a pointer to given instance. +```dae +func int MEM_InstGetOffset(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + The instance to which the pointer is returned + +### `MEM_CpyInst` +Returns a copy of a given instance +```dae +func MEMINT_HelperClass MEM_CpyInst(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + Instance to copy + +??? abstract "example" + Following code + ```dae + selfCopy = MEM_CpyInst (self); + ``` + is equivalent to + ```dae + selfCopy = MEM_PtrToInst (MEM_InstToPtr (self)); + ``` +## Call function +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. + +### Passing Parameters +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. + +#### `MEM_PushIntParam` +Passes an integer as a parameter to the called function. +```dae +func void MEM_PushIntParam (var int param) +``` +**Parameters** + +- `#!dae var int param` + Integer to pass as a function parameter + +#### `MEM_PushInstParam` +Passes an instance as a parameter to the called function. +```dae +func void MEM_PushInstParam (var int inst) +``` +**Parameters** + +- `#!dae var int inst` + Instance to pass as a function parameter + +#### `MEM_PushStringParam` +Passes a string as a parameter to the called function. +```dae +func void MEM_PushStringParam (var string str) +``` +**Parameters** + +- `#!dae var string str` + String to pass as a function parameter + +### The call + +#### `MEM_Call` +Calls a function. +```dae +func void MEM_Call(var func fnc) +``` +**Parameters** + +- `#!dae var func fnc` + Function to be called + +#### `MEM_CallByID` +Calls a function by its ID. +```dae +func void MEM_CallByID (var int symbID) +``` +**Parameters** + +- `#!dae var int symbID` + The ID of the function to be called + +#### `MEM_CallByPtr` +Calls a function by its pointer. +```dae +func void MEM_CallByPtr(var int ptr) +``` +**Parameters** + +- `#!dae var int ptr` + The pointer of the function to be called + +#### `MEM_CallByOffset` +Calls a function by its offset. +```dae +func void MEM_CallByOffset(var int offset) +``` +**Parameters** + +- `#!dae var int offset` + The offset of the function to be called + +#### `MEM_CallByString` +Calls a function by its name. +```dae +func void MEM_CallByString (var string fnc) +``` +**Parameters** + +- `#!dae var string fnc` + The name of the function IN CAPITAL LETTERS. + +### Return value +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). + +#### `MEM_PopIntResult` +Retrieves an integer returned by the called function. +```dae +func int MEM_PopIntResult() +``` +**Return value** + +The function returns an integer returned by the previously called script function. + +#### `MEM_PopStringResult` +Retrieves a daedalus string returned by the called function. +```dae +func string MEM_PopStringResult() +``` +**Return value** + +The function returns a string returned by the previously called script function. + +#### `MEM_PopInstResult` +Retrieves an instance returned by the called function. +```dae +func MEMINT_HelperClass MEM_PopInstResult() +``` +**Return value** + +The function returns an instance returned by the previously called script function. + +## Function stuff +### `MEM_GetFuncID` +Returns the ID of the given function. +```dae +func int MEM_GetFuncID(var func fnc) +``` +**Parameters** + +- `#!dae var func fnc` + The function whose ID is returned + +### `MEM_GetFuncPtr` +Returns the pointer of the given function. +```dae +func int MEM_GetFuncPtr(var func fnc) +``` +**Parameters** + +- `#!dae var func fnc` + The function whose pointer is returned + +### `MEM_GetFuncOffset` +Returns the offset of the given function. +```dae +func int MEM_GetFuncOffset(var func fnc) +``` +**Parameters** + +- `#!dae var func fnc` + The function whose offset is returned + +### `MEM_GetFuncIDByOffset` +[`MEM_GetFuncID`](#mem_getfuncid), but with an offset as a parameter. +```dae +func int MEM_GetFuncIDByOffset(var int offset) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_ReplaceFunc` +Replaces the `f1` function with `f2` function so if you call the first function, the second function is called. +```dae +func void MEM_ReplaceFunc(var func f1, var func f2) +``` +**Parameters** + +- `#!dae var func f1` + Function to replace +- `#!dae var func f2` + Function called instead of `f1` + +## Parser stack + +### `MEM_GetFrameBoundary` +Returns the address/pointer to the boundary of a stack frame (ESP). +```dae +func int MEM_GetFrameBoundary() +``` +### `MEM_GetCallerStackPos` +Retrieves the stack position (pop position) of the caller's caller (look at the example for better understanding). +```dae +func int MEM_GetCallerStackPos() +``` +**Return value** + +The function returns an integer representing the stack position of the caller's caller. + +??? abstract "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()`. + ```dae + func void A(){ + B(); + }; + + func void B(){ + int adr; adr = MEM_GetCallerStackPos(); + // Now, 'adr' will contain the stack position of A. + }; + ``` + +### `MEM_SetCallerStackPos` +Sets the stack position (pop position) of the caller's caller. +```dae +func void MEM_SetCallerStackPos(var int popPos) +``` +**Parameters** + +- `#!dae var int popPos` + An integer parameter representing the new stack position of the caller's caller + +## Get address + +### `MEM_GetAddress_Init` +Initializes the `MEM_GetIntAddress`, `MEM_GetFloatAddress` and `MEM_GetStringAddress` functions. +```dae +func void MEM_GetAddress_Init() +``` + +!!! Tip + It's worth noting that `MEM_GetAddress_Init` is also invoked by the `MEM_InitAll` function. + +### `MEM_GetIntAddress` +Returns an address of a given integer. +```dae +func int MEM_GetIntAddress(var int i) +``` +**Parameters** + +- `#!dae var int i` + Integer whose address is returned + +**Shortcut** + +In addition there is a function **`_@`** with the same signature and functionality as `MEM_GetIntAddress`. + +```dae +func int _@(var int i) +``` + +### `MEM_GetFloatAddress` +Returns an address of a given daedalus float. +```dae +func int MEM_GetFloatAddress(var float f) +``` +**Parameters** + +- `#!dae 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`. + +```dae +func int _@s(var string s) +``` + +### `MEM_GetStringAddress` +Returns an address of a given string. +```dae +func int MEM_GetStringAddress(var string s) +``` +**Parameters** + +- `#!dae 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`. + +```dae +func int _@s(var string s) +``` + +### `STR_GetAddressInit` +Alias to [`MEM_GetAddress_Init`](#mem_getaddress_init), kept for downward compatibility. +```dae +func void STR_GetAddressInit() +``` + +### `STR_GetAddress` +Function similar to `MEM_GetStringAddress`. There is a guarantee, that this function works initialized i.e. invokes [`MEM_GetAddress_Init`](#mem_getaddress_init), but the first time may only return an address of a copy of the string. +```dae +func int STR_GetAddress(var string str) +``` + +## Static arrays +Accessing static arrays like this below is very tedious in Daedalus. +```dae +var int myStaticArray[42]; +``` +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. + +### `MEM_InitStatArrs` +Initializes static arrays read and write functions. +```dae +func void MEM_InitStatArrs() +``` + +### `MEM_WriteStatArr` +Changes the value at the `offset` of a static integer-array. +```dae +func void MEM_WriteStatArr (var int array, var int offset, var int value) +``` +**Parameters** + +- `#!dae var int array` + Array which will be edited +- `#!dae var int offset` + Array index at which value will be edited +- `#!dae var int value` + The new value + +### `MEM_ReadStatArr` +Reads the value at the specific offset of a static integer-array. +```dae +func int MEM_ReadStatArr (var int array, var int offset) +``` +**Parameters** + +- `#!dae var int array` + Array to get a value from +- `#!dae 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. + +### `MEM_WriteStatStringArr` +Changes the value at the `offset` of a static string-array. +```dae +func void MEM_WriteStatStringArr(var string array, var int offset, var string value) +``` +**Parameters** + +- `#!dae var string array` + Array which will be edited +- `#!dae var int offset` + Array index at which value will be edited +- `#!dae var string value` + The new value + +### `MEM_ReadStatStringArr` +Reads the value at the specific offset of a static string-array. +```dae +func string MEM_ReadStatStringArr(var string array, var int offset) +``` +**Parameters** + +- `#!dae var string array` + Array to get a value from +- `#!dae 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. + +## Parser symbol +### `MEM_SetCurrParserSymb` +Makes [`currParserSymb`](#currparsersymb) point to the symbol of the specified instance. +```dae +func void MEM_SetCurrParserSymb (var int inst) +``` +**Parameters** + +- `#!dae var int inst` + Instance to whose symbol `currParserSymb` will be set + +#### `currParserSymb` +An instance representing current parser symbol. +```dae +INSTANCE currParserSymb (zCPar_Symbol); +``` + +### `MEM_FindParserSymbol` +Returns the index of the parser symbol with name `inst` if such a symbol exists. +```dae +func int MEM_FindParserSymbol(var string inst) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_GetSymbolIndex` +Alias to [`MEM_FindParserSymbol`](#mem_findparsersymbol). Returns the index of the parser symbol with name `inst` if such a symbol exists. +```dae +func int MEM_GetSymbolIndex(var string inst) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_GetParserSymbol` +Looks for the parser symbol with the name `inst` and returns a pointer to the appropriate `zCPar_Symbol` structure. +```dae +func int MEM_GetParserSymbol (var string inst) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_GetSymbol` +Alias to [`MEM_GetParserSymbol`](#mem_getparsersymbol). Looks for the parser symbol with the name `inst` and returns a pointer to the appropriate `zCPar_Symbol` structure. +```dae +func int MEM_GetSymbol(var string inst) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_GetSymbolByIndex` +[`MEM_GetParserSymbol`](#mem_getparsersymbol), but with ID (index) as a parameter. +```dae +func int MEM_GetSymbolByIndex(var int id) +``` +**Parameters** + +- `#!dae 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. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/string.md b/docs/zengin/scripts/extenders/ikarus/functions/string.md new file mode 100644 index 0000000000..fbcfebc76f --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/string.md @@ -0,0 +1,291 @@ +# String operations +Collection of Ikarus functions to manipulate and format strings. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L2341) + +## Functions + +### `STR_GetCharAt` +Returns the ASCII value of a character at a specific position in a string. +```dae +func int STR_GetCharAt (var string str, var int pos) +``` +**Parameters** + +- `#!dae var string str` + The input string +- `#!dae var int pos` + The position of the character + +**Return value** + +The function returns the ASCII value of the character at the specified position. + +### `STR_Len` +Returns the length of a string. +```dae +func int STR_Len (var string str) +``` +**Parameters** + +- `#!dae var string str` + The input string + +**Return value** + +The function returns the length of the string in characters. + +### `STR_toChar` +Converts a string to a pointer to its character array. +```dae +func int STR_toChar (var string str) +``` +**Parameters** + +- `#!dae var string str` + The input string + +**Return value** + +The function returns a pointer to the character array representing the input string `str` + +### `STR_FromChar` +Converts a character array to a string. +```dae +func string STR_FromChar(var int char) +``` +**Parameters** + +- `#!dae var int char` + Pointer to the character array + +**Return value** + +The function returns a string representation of the character array. + +### `STR_SubStr` +Extracts a substring from a given string. +```dae +func string STR_SubStr (var string str, var int start, var int count) +``` +**Parameters** + +- `#!dae var string str` + The input string +- `#!dae var int start` + The starting position of the substring +- `#!dae 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. + + +### `STR_Prefix` +Extracts a prefix of a given string, similar to [`STR_SubStr`](#str_substr), but with the starting position set to the first character of the string. +```dae +func string STR_Prefix (var string str, var int len) +``` +**Parameters** + +- `#!dae var string str` + The input string +- `#!dae var int count` + The length of the prefix + +**Return value** + +The function returns a prefix of the input string with the specified length. + +### `STR_Compare` +Compares two strings lexicographically and returns a result indicating their relative order. +```dae +func int STR_Compare(var string str1, var string str2) +``` +**Parameters** + +- `#!dae var string str1` + The first string to compare +- `#!dae 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`. + +??? abstract "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. + + ```dae + int result1 = STR_Compare("A", "B"); + // The 'result1' variable now contains STR_SMALLER + + int result2 = STR_Compare("ABC", "ABC"); + // The 'result2' variable now contains STR_EQUAL + + int result3 = STR_Compare("AA", "A"); + // The 'result3' variable now contains STR_GREATER + + int result4 = STR_Compare("BA", "BB"); + // The 'result4' variable now contains STR_SMALLER + + int result5 = STR_Compare("B", "a"); + // The 'result5' variable now contains STR_SMALLER + + int result6 = STR_Compare("A", ""); + // The 'result6' variable now contains STR_GREATER + ``` + +### `STR_ToInt` +Converts a string to an integer. +```dae +func int STR_ToInt (var string str) +``` +**Parameters** + +- `#!dae 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. + +### `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. +```dae +func int STR_IndexOf(var string str, var string tok) +``` +**Parameters** + +- `#!dae var string str` + The string in which to search for `tok`. +- `#!dae 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. + +??? abstract "Examples" + + ```dae + int index1 = STR_IndexOf("Hello World!", "Hell"); + // The 'index1' variable now contains 0 + + int index2 = STR_IndexOf("Hello World!", "World"); + // The 'index2' variable now contains 6 + + int index3 = STR_IndexOf("Hello World!", "Cake"); + // The 'index3' variable now contains -1 + + int index4 = STR_IndexOf("Hello World!", ""); + // The 'index4' variable now contains 0 + + int index5 = STR_IndexOf("Hello", "Hello World!"); + // The 'index5' variable now contains -1 + + int index6 = STR_IndexOf("hello Hell!", "Hell"); + // The 'index6' variable now contains 6 + + int index7 = STR_IndexOf("", ""); + // The 'index7' variable now contains 0 + ``` + +### `STR_SplitCount` +Counts the number of parts a string splits into when using a specified separator. +```dae +func int STR_SplitCount(var string str, var string separator) +``` +**Parameters** + +- `#!dae var string str` + The input string to be split. +- `#!dae 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. + +??? abstract "Example" + + ```dae + string inputStr = "This is a sentence."; + int count = STR_SplitCount(inputStr, " "); + // The 'count' variable now contains 4 + ``` + +### `STR_Split` +Splits a string into multiple substrings based on a specified separator and returns the substring at a specified offset. +```dae +func string STR_Split(var string str, var string separator, var int offset) +``` + +**Parameters** + +- `#!dae var string str ` + The input string to be split. +- `#!dae var string separator` + The separator character or string used to split the input string. +- `#!dae 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. + +??? abstract "Example" + + ```dae + func void foo() { + string inputStr = "This is a sentence."; + string tok1 = STR_Split(inputStr, " ", 0); // This + string tok2 = STR_Split(inputStr, " ", 1); // is + string tok3 = STR_Split(inputStr, " ", 2); // a + string tok4 = STR_Split(inputStr, " ", 3); // sentence + }; + ``` + At the end of the function, `tok1` contains "This", `tok2` contains "is", `tok3` contains "a", and `tok4` contains "sentence.". + +### `STR_Upper` +Converts a string to uppercase. +```dae +func string STR_Upper(var string str) +``` +**Parameters** + +- `#!dae 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. + +### `STR_Lower` +Converts a string to lowercase. +```dae +func string STR_Lower(var string str) +``` +**Parameters** + +- `#!dae 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. diff --git a/docs/zengin/scripts/extenders/ikarus/functions/time_benchmark.md b/docs/zengin/scripts/extenders/ikarus/functions/time_benchmark.md new file mode 100644 index 0000000000..eb281fd746 --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/functions/time_benchmark.md @@ -0,0 +1,146 @@ +# Time and Benchmark +Set of functions to time measurement and Benchmark. + +## Initialization +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. + +```dae +MEM_InitAll(); +``` + +## Implementation +[:material-github: Ikarus.d on GitHub](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L4596-L4714) + +## Time functions + +### `MEM_GetSystemTime` +Returns the elapsed time since Gothic started. +```dae +func int MEM_GetSystemTime() +``` +**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. + +### `MEM_GetPerformanceCounter` +Call to the WinAPI [`QueryPerformanceCounter`](https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter) function. +```dae +func int MEM_GetPerformanceCounter() +``` +**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. + +## Benchmark functions + +!!! 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 + - Elementary calculation (e.g., i = i + 1): 130ns + - Wld_IsTime: 200ns + - MEM_ReadInt, MEM_WriteInt: 350ns + - Hlp_StrCmp("Hello", "Hello"): 500ns + - MEM_InstToPtr: 1400ns + - (small) Allocate and free memory: 9700ns + - CALL__stdcall (in empty function): 29000ns + - MEM_GetParserSymb: 280000ns + + - Iteration of the benchmark function: 300ns + ``` + +### `MEM_BenchmarkMS` +Benchmark of the execution time for a specified function. (Milliseconds) +```dae +func int MEM_BenchmarkMS(var func f) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark + +**Return value** + +The function returns the duration of a function execution in milliseconds. + +### `MEM_BenchmarkMMS` +Benchmark of the execution time for a specified function. (microseconds) +```dae +func int MEM_BenchmarkMMS(var func f) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark + +**Return value** + +The function returns the duration of a function execution in microseconds. + +### `MEM_BenchmarkPC` +Benchmark of the execution time for a specified function, using the [Performancecounter](#mem_getperformancecounter). +```dae +func int MEM_BenchmarkMS(var func f) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark + +**Return value** + +The function returns the number of [Performancecounter](#mem_getperformancecounter) ticks the function needs. + +### `MEM_BenchmarkMS_N` +[`MEM_BenchmarkMS`](#mem_benchmarkms), but with the parameter to specify the number of function runs. +```dae +func int MEM_BenchmarkMS_N(var func f, var int n) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark +- `#!dae var int n` + Number of runs + +**Return value** + +The function returns a summed duration of multiple (`n`) runs of the function in milliseconds. + +### `MEM_BenchmarkMMS_N` +[`MEM_BenchmarkMMS`](#mem_benchmarkmms), but with the parameter to specify the number of function runs. +```dae +func int MEM_BenchmarkMMS_N(var func f, var int n) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark +- `#!dae var int n` + Number of runs + +**Return value** + +The function returns a summed duration of multiple (`n`) runs of the function in microseconds. + +### `MEM_BenchmarkPC_N` +[`MEM_BenchmarkPC`](#mem_benchmarkpc), but with the parameter to specify the number of function runs. +```dae +func int MEM_BenchmarkPC_N(var func f, var int n) +``` +**Parameters** + +- `#!dae var func f` + Function to benchmark +- `#!dae var int n` + Number of runs + +**Return value** + +The function returns a summed number of [Performancecounter](#mem_getperformancecounter) ticks needed to execute function multiple (`n`) times. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/ikarus/functions/win_utilities.md b/docs/zengin/scripts/extenders/ikarus/functions/win_utilities.md index 74597a9ff8..fc384f4c94 100644 --- a/docs/zengin/scripts/extenders/ikarus/functions/win_utilities.md +++ b/docs/zengin/scripts/extenders/ikarus/functions/win_utilities.md @@ -70,7 +70,7 @@ func int VirtualProtect(var int lpAddress, var int dwSize, var int flNewProtect) - `#!dae var int dwSize` The size of the region whose access protection attributes are to be changed, in bytes. - `#!dae var int flNewProtect` - The memory protection option. All options can be found [here](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1908). + The memory protection option. All options can be found [here](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1907-L1919). **Return value** @@ -103,7 +103,7 @@ func int MEM_MessageBox(var string txt, var string caption, var int type) - `#!dae var string caption` Header of MessageBox. - `#!dae var int type` - Type of MessageBox. All types listed [here](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1957). + Type of MessageBox. All types listed [here](https://github.com/Lehona/Ikarus/blob/master/Ikarus.d#L1956-L1992). ### `MEM_InfoBox` Alias to `MEM_MessageBox` with "Information:" header and `MB_OK | MB_ICONINFORMATION` type. diff --git a/docs/zengin/scripts/extenders/ikarus/index.md b/docs/zengin/scripts/extenders/ikarus/index.md index 474a9274c8..d9bcdd48d0 100644 --- a/docs/zengin/scripts/extenders/ikarus/index.md +++ b/docs/zengin/scripts/extenders/ikarus/index.md @@ -7,5 +7,16 @@ Ikarus is a Daedalus library for Gothic. It exploits the interpreter to allow ar | GitHub | [:material-github: Ikarus](https://github.com/Lehona/Ikarus) | | Forum | [:material-forum: Ikarus](https://forum.worldofplayers.de/forum/threads/1299679-Skriptpaket-Ikarus-4) | +!!! Trivia "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](../../../tools/zSpy.md) 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](../../../tools/zSpy.md) (for example, to narrow down where the crash is occurring). It's worth enabling debug messages by [`MEM_SetShowDebug`](functions/debug.md#mem_setshowdebug) and the text filter (Options -> Textfilter) in [zSpy](../../../tools/zSpy.md#configuration). + !!! Note Ikarus is hosted on [GitHub](https://github.com/Lehona/Ikarus) and the documentation is [built in](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Doc.d). The translation is planned. diff --git a/docs/zengin/scripts/extenders/ikarus/index.pl.md b/docs/zengin/scripts/extenders/ikarus/index.pl.md index 204d188dc4..6d1f1af0b7 100644 --- a/docs/zengin/scripts/extenders/ikarus/index.pl.md +++ b/docs/zengin/scripts/extenders/ikarus/index.pl.md @@ -7,5 +7,16 @@ Ikarus jest biblioteką Daedalusa - języka skryptowego Gothica. Wykorzystuje in | GitHub | [:material-github: Ikarus](https://github.com/Lehona/Ikarus) | | Forum | [:material-forum: Ikarus](https://forum.worldofplayers.de/forum/threads/1299679-Skriptpaket-Ikarus-4) | +!!! Trivia "Notatka autora (Sektenspinner)" + Ten pakiet skryptów nie bez powodu nazywa się **Ikarus**: + + Można opuścić granice Dedala, ale można też rozbić się i spalić. Na przykład odczyt z nieprawidłowych adresów nie wywoła ostrzeżenia [zSpy](../../../tools/zSpy.md), ale spowoduje wyjście do pulpitu wraz z Access Violation. Nie jest to powód do paniki, ale wymaga tolerancji na frustrację (co może być ogólnie przydatne dla skrypterów). + + Oczywiście tak spektakularnie wyglądające błędy można naprawić, a przy systematycznej pracy w skupieniu można osiągnąć coś sensownego. + + W skrócie: wymagana jest dodatkowa ostrożność! Błąd prowadzący do awarii nie jest czymś, czego chciałbyś w wydanej wersji. Ale jeśli pracujesz czysto i intensywnie testujesz, nie jest to taka wielka sprawa. + + Dobrym przyjacielem w debugowaniu awarii jest niewątpliwie `PrintDebug`. Umożliwia wysyłanie wiadomości do [zSpy](../../../tools/zSpy.md) (na przykład w celu zawężenia miejsca wystąpienia awarii). Warto włączyć komunikaty debugowania za pomocą [`MEM_SetShowDebug`](functions/debug.md#mem_setshowdebug) i filtr tekstowy (Opcje -> Textfilter) w [zSpy](../../../tools/zSpy.md#configuration). + !!! Note Ikarus jest hostowany na [GitHubie](https://github.com/Lehona/Ikarus) i posiada wbudowaną [dokumentacje](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Doc.d). Jej tłumaczenie jest w planach. diff --git a/docs/zengin/scripts/extenders/ikarus/setup.md b/docs/zengin/scripts/extenders/ikarus/setup.md new file mode 100644 index 0000000000..75b4af15cb --- /dev/null +++ b/docs/zengin/scripts/extenders/ikarus/setup.md @@ -0,0 +1,123 @@ +--- +title: Setup +--- + +# Ikarus Setup + +## Download +First you need to download ikarus from the [official github repository](https://github.com/Lehona/Ikarus). 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. + +## File location +Before unpacking the downloaded archive it's needed to create a dedicated folder in `\_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. + +## Parsing +Ikarus consists of three main parts, [constants](./constants.md), classes and the Ikarus core. It's essential to parse these in a specific order. Additionally, there is a [floats package](floats.md) which isn't essential, but it is highly recommended to parse it, especially if you are working with [LeGo](../lego/index.md) that depends on it. + +The Ikarus Core is identical for both Gothic 1 and 2 and is contained in a single file, [`Ikarus.d`](https://github.com/Lehona/Ikarus/blob/master/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.src" + ``` + _INTERN\CONSTANTS.D + _INTERN\CLASSES.D + MOD\IKARUS\Ikarus_Const_G2.d + MOD\IKARUS\EngineClasses_G2\*.d + MOD\IKARUS\Ikarus.d + MOD\IKARUS\float.d + ``` +=== "Gothic.src (Ikarus 1.2.1+)" + ``` + _INTERN\CONSTANTS.D + _INTERN\CLASSES.D + MOD\IKARUS\IKARUS_G2.SRC + ``` + +## Initialization +Before you can use Ikarus in your scripts, it must be properly initialized. The initialization process differs between Gothic 1 and Gothic 2. + +### `MEM_InitAll` +This is main ikarus initialization function, however it consists of some smaller initialization functions. +=== "Declaration" + ```dae + func void MEM_InitAll() + ``` + +=== "Definition" + + ```dae + func void MEM_InitAll() { + if (!MEMINT_ReportVersionCheck()) { + return; + }; + + MEM_ReinitParser(); /* depends on nothing */ + MEM_InitLabels(); /* depends in MEM_ReinitParser */ + MEM_InitGlobalInst(); /* depends on MEM_ReinitParser */ + + /* now I can use MEM_ReplaceFunc, MEM_GetFuncID */ + MEM_GetAddress_Init(); /* depends on MEM_ReinitParser and MEM_InitLabels */ + /* now the nicer operators are available */ + + MEM_InitStatArrs(); /* depends on MEM_ReinitParser and MEM_InitLabels */ + ASMINT_Init(); + + MEMINT_ReplaceLoggingFunctions(); + MEMINT_ReplaceSlowFunctions(); + MEM_InitRepeat(); + + /* takes a wail the first time it is called. + call it to avoid delay later */ + var int dump; dump = MEM_GetFuncIDByOffset(0); + }; + ``` + +=== "List of functions" + - [MEM_ReinitParser](functions/parser.md#mem_reinitparser) + - [MEM_InitLabels](functions/jumps_loops.md#initialization) + - [MEM_InitGlobalInst](functions/objects.md#mem_initglobalinst) + - [MEM_GetAddress_Init](functions/parser.md#mem_getaddress_init) + - [MEM_InitStatArrs](functions/parser.md#mem_initstatarrs) + - [ASMINT_Init](functions/asm.md#asmint_init) + - [MEM_InitRepeat](functions/jumps_loops.md#initialization_1) + +### Gothic 1 +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_` function (e.g. `INIT_SURFACE`,`INIT_OLDCAMP` etc.). `INIT_SUB_` functions can be skipped in that process. + +Then in your `INIT_GLOBAL` function you call `MEM_InitAll()` initialization function. + +```dae title="Startup.d" +FUNC VOID INIT_GLOBAL() +{ + // Init Ikarus + MEM_InitAll (); +}; + +// [...] + +func VOID INIT_SURFACE () +{ + Init_Global(); + INIT_SUB_SURFACE (); +}; +// [...] +``` + +### Gothic 2 +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. + +```dae title="Startup.d" +FUNC VOID INIT_GLOBAL() +{ + // Init Ikarus + MEM_InitAll (); +}; + +// [...] +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/index.md b/docs/zengin/scripts/extenders/index.md index 20750cbec1..f841092f5e 100644 --- a/docs/zengin/scripts/extenders/index.md +++ b/docs/zengin/scripts/extenders/index.md @@ -1,3 +1,4 @@ # Daedalus extenders -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](ikarus/index.md) and a collection of packages [LeGo](lego/index.md) built on top of that. Not so recently, an additional script packet was made (and is actively being worked on) [AF Script Packet](afsp/index.md) that offers even more functionality and is built on tom of Ikarus & LeGo. -With the adoption of Union and plugins the Union system can use a new extender emerged called [zParserExtender](../../scripts/extenders/zparserextender). Other Union plugins can, of course, implement their own external functions. +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](ikarus/index.md) and a collection of packages [LeGo](lego/index.md) built on top of that. Not so recently, an additional script packet was made (and is actively being worked on) [AF Script Packet](afsp/index.md) 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](zparserextender/index.md). 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](standalone/index.md) section. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/index.pl.md b/docs/zengin/scripts/extenders/index.pl.md new file mode 100644 index 0000000000..0992559a0d --- /dev/null +++ b/docs/zengin/scripts/extenders/index.pl.md @@ -0,0 +1,4 @@ +# Extendery Daedalusa +Extendery to pakiety skryptowe rozszerzające składnię Daedalusa, która może być dosyć ograniczająca. Przez lata społeczność stworzyła całkiem sporo takich extenderów. Zanim pojawił się Union, standardową metodą na interfejs z silnikiem było wykorzystanie [Ikarusa](ikarus/index.md) i zbudowanej na jego bazie kolekcji pakietów [LeGo](lego/index.md). Nie tak niedawno powstał dodatkowy pakiet skryptowy (a prace nad nim wciąż trwają) [AF Script Packet](afsp/index.md), który oferuje jeszcze więcej funkcji i jest zbudowany na bazie Ikarusa i LeGo. +Wraz z pojawieniem się Uniona i jego systemu pluginów powstał nowy extender o nazwie [zParserExtender](zparserextender/index.md). Oczywiście również inne pluginy mogą implementować własne funkcje zewnętrzne. +Wiele skryptów jest również rozsianych po forach Gothicowych, a dokumentacje niektórych z nich można znaleźć w sekcji [Samodzielne](standalone/index.md). \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/applications/LeGo_applications.d b/docs/zengin/scripts/extenders/lego/applications/LeGo_applications.d new file mode 100644 index 0000000000..9aad19ad0d --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/applications/LeGo_applications.d @@ -0,0 +1,651 @@ +// ========================================================= +// +// Anim8 +// +// ========================================================= + +/// Creates a new Anim8 object that can be filled with commands. +/// +/// @param initialValue The initial value to start animating from. Can be an integer, or an Ikarus float. +/// @param 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 The function returns handle of the Anim8 object. +func int Anim8_New(var int initialValue, var int IsFloat) {}; + +/// Creates a new Anim8 object with advanced options. Extends the Anim8_New function. +/// +/// @param value The initial value to start animating from. Can be an integer, or an Ikarus float. +/// @param handler This function is called whenever the object is updated. +/// @param data Optional parameter to send an additional value to the handler function. If data == 0, it is ignored. +/// @param 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 The function returns handle of the Anim8 object. +func int Anim8_NewExt(var int value, var func handler, var int data, var int IsFloat) {}; + +/// Deletes an Anim8 object created with Anim8_New. +/// +/// @param handle Handle returned from Anim8_New. +func void Anim8_Delete(var int handle) {}; + +/// Get current value of the object. +/// +/// @param handle Handle returned from Anim8_New. +/// @return The function returns value of the object. +func int Anim8_Get(var int handle) {}; + +/// Sets the value of the object. +/// +/// @param handle Handle returned from Anim8_New. +/// @param value New value of the object. +func void Anim8_Set(var int handle, var int value) {}; + +/// Indicates whether the object is empty, i.e. has no more commands to process. +/// +/// @param handle Handle returned from Anim8_New. +/// @return The function returns TRUE if object is empty (has no more commands), FALSE is returned otherwise. +func int Anim8_Empty(var int handle) {}; + +/// If desired, Anim8 can automatically delete an object after it is empty. +/// +/// @param handle Handle returned from Anim8_New. +/// @param on TRUE: enable, FALSE: disable. +func void Anim8_RemoveIfEmpty(var int handle, var int on) {}; + +/// 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. +/// +/// @param handle Handle returned from Anim8_New. +/// @param on TRUE: enable, FALSE: disable. +func void Anim8_RemoveDataIfEmpty(var int handle, var int on) {}; + +/// Packet core. Gives the object a new command to process. +/// +/// @param handle Handle returned from Anim8_New. +/// @param target Target value of this command. When the object's value has reached this value, the command is considered completed and deleted. +/// @param span Action duration in milliseconds. +/// @param interpol What form of movement is used (See constants for this). +func void Anim8(var int handle, var int target, var int span, var int interpol) {}; + +/// 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. +/// +/// @param handle Handle returned from Anim8_New. +/// @param 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. +/// @param span Action duration in milliseconds. +/// @param interpol What form of movement is used (See constants for this). +func void Anim8q(var int handle, var int target, var int span, var int interpol) {}; + +/// Registers a function to be called when the object is deleted (e.g. by Anim8_RemoveIfEmpty) +/// +/// @param handle Handle returned from Anim8_New. +/// @param dfnc This function is called when the object is deleted. +func void Anim8_CallOnRemove(var int handle, var func dfnc) {}; + +// ========================================================= +// +// Bars +// +// ========================================================= + +/// Creates a new bar from a constructor instance. +/// +/// @param inst Constructor instance of Bar class +/// @return The function returns the address of the new bar, aka the handle. +func int Bar_Create(var int inst) {}; + +/// Deletes a bar from the screen and from memory. +/// +/// @param bar Handle returned from Bar_Create +func void Bar_Delete(var int bar) {}; + +/// Changes a bar's maximum value but does not update its bar length (only Bar_SetPercent, Bar_SetPromille, and Bar_SetValue) +/// +/// @param bar Handle returned from Bar_Create +/// @param max New maximum value +func void Bar_SetMax(var int bar, var int max) {}; + +/// Sets the value of the bar. +/// +/// @param bar Handle returned from Bar_Create +/// @param val New value of the bar +func void Bar_SetValue(var int bar, var int val) {}; + +/// Sets the value of the bar but as a percentage (0..100). +/// +/// @param bar Handle returned from Bar_Create +/// @param perc New value of the bar in percent +func void Bar_SetPercent(var int bar, var int perc) {}; + +/// Sets the value of the bar but per mille (0..1000). +/// +/// @param bar Handle returned from Bar_Create +/// @param pro New value of the bar in per mille +func void Bar_SetPromille(var int bar, var int pro) {}; + +/// Hides a bar. It will not be deleted. +/// +/// @param bar Handle returned from Bar_Create +func void Bar_Hide(var int bar) {}; + +/// Displays a bar again after using Bar_Hide. +/// +/// @param bar Handle returned from Bar_Create +func void Bar_Show(var int bar) {}; + +/// Move the bar to a virtual position. +/// +/// @param bar Handle returned from Bar_Create +/// @param x New horizontal position in virtual coordinates +/// @param y New vertical position in virtual coordinates +func void Bar_MoveTo(var int bar, var int x, var int y) {}; + +/// Move the bar to pixel position. +/// +/// @param bar Handle returned from Bar_Create +/// @param x New horizontal position in pixels +/// @param y New vertical position in pixels +func void Bar_MoveToPxl(var int bar, var int x, var int y) {}; + +/// Sets the transparency of the bar. +/// +/// @param bar Handle returned from Bar_Create +/// @param alpha Transparency value (0..255) +func void Bar_SetAlpha(var int bar, var int alpha) {}; + +/// Sets the foreground texture of the bar. +/// +/// @param bar Handle returned from Bar_Create +/// @param barTex The new foreground texture +func void Bar_SetBarTexture(var int bar, var string barTex) {}; + +/// Sets the background texture of the bar. +/// +/// @param bar Handle returned from Bar_Create +/// @param backTex The new background texture +func void Bar_SetBackTexture(var int bar, var string backTex) {}; + +/// Resize an existing bar. +/// +/// @param bar Handle returned from Bar_Create +/// @param width New width in virtual coordinates +/// @param height New height in virtual coordinates +func void Bar_Resize(var int bar, var int width, var int height) {}; + +/// Resize existing bar (in pixels). +/// +/// @param bar Handle returned from Bar_Create +/// @param x New width in pixels +/// @param y New height in pixels +func void Bar_ResizePxl(var int bar, var int x, var y) {}; + +// ========================================================= +// +// Bloodsplats +// +// ========================================================= + +/// Puts a blood splatter on the screen. +/// +/// @param damage The damage (affects the size of the splatter) +func void Bloodsplat(var int damage) {}; + +/// Pretty pointless feature that smears the entire screen. +func void Bloodsplats_Rage() {}; + +/// `oCNpc::GetPerceptionFunc` engine function wrapper. +/// +/// @param npc NPC whose perception is checked +/// @param type Checked perception type (from Constants.d) +/// @return The function returns the state of NPCs selected perception. +func int Npc_GetPercFunc(var C_Npc npc, var int type) {}; + +// ========================================================= +// +// Buffs +// +// ========================================================= + +/// Applies a status effect to an NPC. +/// +/// @param npc NPC to be affected by this effect +/// @param buff The instance of the effect to apply to the NPC +/// @return The function returns the handle of the buff, which was just generated. +func int Buff_Apply(var C_NPC npc, var int buff) {}; + +/// Buff_Apply, but nothing happens if a status effect of that kind is already on the NPC. +/// +/// @param npc NPC to be affected by this effect +/// @param buff The instance of the effect to apply to the NPC +/// @return The function returns the handle of the buff, which was just generated or 0 if the buff is already applied on the NPC. +func int Buff_ApplyUnique(var C_NPC npc, var int buff) {}; + +/// Buff_Apply, but if a status effect of this type is already affecting the NPC, the duration will be reset. +/// +/// @param npc NPC to be affected by this effect +/// @param buff The instance of the effect to apply to the NPC +/// @return The function returns the handle of the buff, which was just generated or refreshed. +func int Buff_ApplyOrRefresh(var C_NPC n, var int buff) {}; + +/// Resets the duration of the buff. +/// +/// @param buffHandle Handle of the buff to refresh +func void Buff_Refresh(var int buffHandle) {}; + +/// Removes the buff from all NPCs. +/// +/// @param buffHandle Handle of the buff to remove +func void Buff_Remove(var int buffHandle) {}; + +/// Removes the buffs from the NPC. +/// +/// @param npc NPC whose buff should be removed +/// @param buffInstance The instance of the buff to remove +func void Buff_RemoveAll(var C_NPC npc, var int buffInstance) {}; + +/// Returns a pointer to the NPC, which is affected by the buff. +/// +/// @param buffHandle Handle of the buff +/// @return The function returns a pointer to the NPC, which is affected by the buff. +func int Buff_GetNpc(var int buffHandle) {}; + +/// Checks if the NPC already has an effect applied. +/// +/// @param npc Checked NPC +/// @param buff The instance of the effect +/// @return The function returns TRUE if the NPC has an effect applied. FALSE is returned otherwise. +func int Buff_Has(var C_NPC npc, var int buff) {}; + +/// Same as MEM_GetFuncID but gets the current instance. +/// +/// @param f Function whose ID is got +/// @return The function returns the ID of the given function. +func int SAVE_GetFuncID(var func f) {}; + +// ========================================================= +// +// Buttons +// +// ========================================================= + +/// Creates a button. It is initially hidden (not visible and does not react to the mouse). +/// +/// @param posx The horizontal position of the button in virtual coordinates +/// @param posy The vertical position of the button in virtual coordinates +/// @param width Width of the button in virtual coordinates +/// @param height Height of the button in virtual coordinates +/// @param tex Name of the button texture +/// @param on_enter This function is called when the mouse enters the button +/// @param on_leave This function is called when the mouse leaves the button +/// @param on_click This function is called when the user performs a mouse click on the button (left mouse button) +/// @return The function returns a handle to created button. +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) {}; + +/// Button_Create with pixels instead of virtual coordinates. +/// +/// @param posx The horizontal position of the button in pixels +/// @param posy The vertical position of the button in pixels +/// @param width Width of the button in pixels +/// @param height Height of the button in pixels +/// @param tex Name of the button texture +/// @param on_enter This function is called when the mouse enters the button +/// @param on_leave This function is called when the mouse leaves the button +/// @param on_click This function is called when the user performs a mouse click on the button (left mouse button) +/// @return The function returns a handle to created button. +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) {}; + +/// Completely deletes a button. +/// +/// @param hndl Handle returned from `Button_Create` +func void Button_Delete(var int hndl) {}; + +/// Shows the button and makes it respond to the mouse. +/// +/// @param hndl Handle returned from `Button_Create` +func void Button_Show(var int hndl) {}; + +/// Hides the button and disables it, so it is no longer responding to the mouse. +/// +/// @param hndl Handle returned from `Button_Create` +func void Button_Hide(var int hndl) {}; + +/// Sets the texture of the button. +/// +/// @param hndl Handle returned from `Button_Create` +/// @param tex Name of the new texture +func void Button_SetTexture(var int hndl, var string tex) {}; + +/// Displays a centered text on the button. +/// +/// @param hndl Handle returned from `Button_Create` +/// @param caption The text to be displayed +/// @param font The font in which the text should be displayed +func void Button_SetCaption(var int hndl, var string caption, var string font) {}; + +/// Attaches a mouseover box to the cursor. +/// +/// @param text The text in the mouseover box +/// @param font The font of the text +func void Button_CreateMouseover(var string text, var string font) {}; + +/// Deletes the mouseover box. +func void Button_DeleteMouseover() {}; + +/// Activates the button, so it reacts to the mouse. Does not change the visibility. +/// +/// @param hndl Handle returned from `Button_Create` +func void Button_Activate(var int hndl) {}; + +/// Disables the button, so it no longer reacts to the mouse. +/// +/// @param hndl Handle returned from `Button_Create` +func void Button_Deactivate(var int hndl) {}; + +/// Sets the user data of the button, an integer, to give the button individual information. +/// +/// @param hndl Handle returned from `Button_Create` +/// @param data Individual integer of the button (part of the internal `_Button` class) +func void Button_SetUserData(var int hndl, var int data) {}; + +/// Gets the user data of the button. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the user data of the button. +func int Button_GetUserData(var int hndl) {}; + +/// Gets the status of the button as a bit field. See User Constants for possible states. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the status of the button. +func int Button_GetState(var int hndl) {}; + +/// Moves the button by the given value in pixels. `posx = posx + nposx` +/// +/// @param hndl Handle returned from `Button_Create` +/// @param nposx X-axis shift in pixels +/// @param nposy Y-axis shift in pixels +func void Button_Move(var int hndl, var int nposx, var int nposy) {}; + +/// Moves the button by the given value in virtual coordinates. `posx = posx + nposx` +/// +/// @param hndl Handle returned from `Button_Create` +/// @param nposx X-axis shift in virtual coordinates +/// @param nposy Y-axis shift in virtual coordinates +func void Button_MoveVrt(var int hndl, var int nposx, var int nposy) {}; + +/// Moves a button to the given position in pixels. `posx = nposx` +/// +/// @param hndl Handle returned from `Button_Create` +/// @param nposx New horizontal position in pixels +/// @param nposy New vertical position in pixels +func void Button_MoveTo(var int hndl, var int nposx, var int nposy) {}; + +/// Moves a button to the given position in virtual coordinates. `posx = nvposx` +/// +/// @param hndl Handle returned from `Button_Create` +/// @param nvposx New horizontal position in virtual coordinates +/// @param nvposy New vertical position in virtual coordinates +func void Button_MoveToVrt(var int hndl, var int nvposx, var int nvposy) {}; + +/// Returns the button's `zCView` as a handle. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the button's `zCView` as a handle. +func int Button_GetViewHandle(var int hndl) {}; + +/// Returns the button's `zCView` as a pointer. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the button's `zCView` as a pointer. +func int Button_GetViewPtr(var int hndl) {}; + +/// Returns the button's `zCView` as an object. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the button's `zCView` as an object. +func zCView Button_GetView(var int hndl) {}; + +/// Returns the pointer to the text of the button. +/// +/// @param hndl Handle returned from `Button_Create` +/// @return The function returns the pointer to the text of the button. +func int Button_GetCaptionPtr(var int hndl) {}; + +// ========================================================= +// +// ConsoleCommands +// +// ========================================================= + +/// Registers a new console command. +/// +/// @param 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. +/// @param cmdPrefix This is a command, which can be entered in the console. +/// @param description This text appears next to the command (in zSpy) when you use the help command in the console. +func void CC_Register(var func f, var string cmdPrefix, var string description) {}; + +/// Removes a function from the console commands. +/// +/// @param f This function will be removed, i.e. the associated command will no longer work. +func void CC_Remove(var func f) {}; + +/// Checks whether the function passed is already part of a console command. +/// +/// @param f Function being checked +/// @return The function returns TRUE if there is a corresponding function, FALSE is returned otherwise. +func int CC_Active(var func f) {}; + +// ========================================================= +// +// Cursor +// +// ========================================================= + +/// Hides the displayed mouse cursor. +func void Cursor_Hide() {}; + +/// Shows the mouse cursor. +func void Cursor_Show() {}; + +/// Can manually enable or disable the mouse. +/// +/// @param enabled TRUE - Mouse activated +func void SetMouseEnabled(var int enabled) {}; + +// ========================================================= +// +// Dialoggestures +// +// ========================================================= + +/// With this function the dialog gestures for all NPCs can be overridden. +/// +/// The full name of the animation can be described as follows: +/// "DIAG_Prefix" + aniName + "DIAG_Suffix" + ((rand() % (max - (min - 1))) + min).ToString("00"); +/// +/// "DIAG_Prefix" and "DIAG_Suffix" are user constants. +/// +/// @param AniName The new dialogue gesture +/// @param Min Lowest animation number +/// @param Max Highest animation number +func void DIAG(var string AniName, var int Min, var int Max) {}; + +/// Resets the dialog gestures to the default. +func void DIAG_Reset() {}; + +/// Sets animation directly. +/// +/// @param AniName Animation name +func void DIAG_SetAni(var string AniName) {}; + +/// Sets animation numbers directly. +/// +/// @param Min Lowest animation number +/// @param Max Highest animation number +func void DIAG_SetMinMax(var int Min, var int Max) {}; + +// ========================================================= +// +// Gamestate +// +// ========================================================= + +/// Adds a listener/handler to the game-state event. +/// +/// @param listener This function will be called on a game-state change. The current game-state is passed as a parameter. +func void Gamestate_AddListener(var func listener) {}; + +/// Removes game-state listener. +/// +/// @param listener Listener function to be removed. +func void Gamestate_RemoveListener(var func listener) {}; + +// ========================================================= +// +// Names +// +// ========================================================= + +/// Should be set in InitGlobal(). +/// +/// @param npc The NPC to be named +/// @param name The name of the NPC +func void SetName(var C_NPC npc, var string name) {}; + +/// Permanently displays the name set by SetName function above the NPC. +/// +/// @param npc The NPC whose name should be shown +func void ShowName(var C_NPC npc) {}; + +// ========================================================= +// +// Render +// +// ========================================================= + +/// Generates the render of an item, with a manually specified priority. +/// +/// @param itemInst The instance of the item to render +/// @param x1 The top left coordinate of the view +/// @param y1 The top left coordinate of the view +/// @param x2 The bottom right coordinate of the view +/// @param y2 The bottom right coordinate of the view +/// @param priority The priority of this render object +/// +/// @return A handle of the render object +func int Render_AddItemPrio(var int itemInst, var int x1, var int y1, var int x2, var int y2, var int priority) {}; + +/// Generates the render of an item, with priority set to 0. +/// +/// @param itemInst The instance of the item to render +/// @param x1 The top left coordinate of the view +/// @param y1 The top left coordinate of the view +/// @param x2 The bottom right coordinate of the view +/// @param y2 The bottom right coordinate of the view +/// +/// @return A handle of the render object +func int Render_AddItem(var int itemInst, var int x1, var int y1, var int x2, var int y2) {}; + +/// Generates the render of a View, with a manually specified priority. +/// +/// @param view A handle to a View +/// @param priority The priority of this render object +/// +/// @return A handle of the render object +func int Render_AddViewPrio(var int view, var int priority) {}; + +/// Generates the render of a View, with priority set to 0. +/// +/// @param view A handle to a View +/// +/// @return A handle of the render object +func int Render_AddView(var int view) {}; + +/// Opens a render object. Only open render objects are displayed. +/// +/// @param handle Handle of a render object +func void Render_OpenView(var int handle) {}; + +/// Closes a render object. Only open render objects are displayed. +/// +/// @param handle Handle of a render object +func void Render_CloseView(var int handle) {}; + +/// Deletes a render object. The associated view is deleted automatically. +/// +/// @param handle Handle of a render object +func void Render_Remove(var int handle) {}; + +// ========================================================= +// +// Trialoge +// +// ========================================================= + +/// Sektenspinner's function. Makes NPC equip a weapon. +/// +/// @param slf NPC to have a weapon equipped +/// @param ItemInstance Weapon instance ID to be equipped +func void EquipWeapon(var C_NPC slf, var int ItemInstance) {}; + +/// Returns NPC's equipped armor. +/// +/// @param slf NPC to get the armor from +/// +/// @return Instance of armor worn by the NPC +func int Npc_GetArmor(var C_NPC slf) {}; + +/// Returns NPC's equipped melee weapon. +/// +/// @param slf NPC to get the weapon from +/// +/// @return Instance ID of the melee weapon equipped by the NPC +func int Npc_GetMeleeWeapon(var C_NPC slf) {}; + +/// Returns NPC's equipped ranged weapon. +/// +/// @param slf NPC to get the weapon from +/// +/// @return Instance ID of the ranged weapon equipped by the NPC +func int Npc_GetRangedWeapon(var C_NPC slf) {}; + +/// Swaps NPCs equipped weapon. +/// +/// @param slf NPC to perform the operation on +/// @param itm0 Instance ID of the item to remove +/// @param itm1 Instance ID of the item to create and equip +func void Npc_TradeItem(var C_NPC slf, var int itm0, var int itm1) {}; + +/// Sektenspinner's function that updates the dialogue camera. (Used internally.) +func void DiaCAM_Update() {}; + +/// Completely disable the dialogue cameras. +func void DiaCAM_Disable() {}; + +/// Resets the dialogue cameras to the default settings. +func void DiaCAM_Enable() {}; + +/// Makes self and other wait for each other, e.g., for AI_GotoWP actions for synchronization. +func void TRIA_Wait() {}; + +/// Invites an NPC into a conversation. Must be called before TRIA_Start. +/// +/// @param slf The invited NPC +func void TRIA_Invite(var C_NPC slf) {}; + +/// Starts trialogues. Before that, all NPCs should be invited by TRIA_Invite. +func void TRIA_Start() {}; + +/// Similar to TRIA_Wait but applies to all participating NPCs. +func void TRIA_Barrier() {}; + +/// Sets the called npc to self. +/// +/// @param n0 NPC to set to self +func void TRIA_Next(var C_NPC n0) {}; + +/// Starts a tracking shot. +/// +/// @param evt The name of the tracking shot in Spacer. If an empty string is passed, the running tracking shot will be aborted. +func void TRIA_Cam(var string evt) {}; + +/// Ends an ongoing trialogue. Must always be called at the end; otherwise, no further trialogues can be started. +func void TRIA_Finish() {}; diff --git a/docs/zengin/scripts/extenders/lego/applications/anim8.md b/docs/zengin/scripts/extenders/lego/applications/anim8.md index 9cd52d2ec5..74914f20f9 100644 --- a/docs/zengin/scripts/extenders/lego/applications/anim8.md +++ b/docs/zengin/scripts/extenders/lego/applications/anim8.md @@ -1,9 +1,13 @@ +--- +title: Anim8 +description: LeGo package for "animating" float values over a period of time +--- # Anim8 -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. +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`](../tools/interface.md#prints) from [Interface](../tools/interface.md) uses Anim8. ## Dependencies -- Floats +- [Floats](../../ikarus/floats.md) ## Initialization Initialize with `LeGo_Anim8` flag. @@ -32,7 +36,7 @@ func int Anim8_New(var int initialValue, var int IsFloat) The function returns handle of the Anim8 object. ### `Anim8_NewExt` -Creates a new Anim8 object with advanced options. Extends the `Anim8_New` function. +Creates a new Anim8 object with advanced options. Extends the [`Anim8_New`](#anim8_new) function. ```dae func int Anim8_NewExt(var int value, var func handler, var int data, var int IsFloat) ``` @@ -55,14 +59,14 @@ func int Anim8_NewExt(var int value, var func handler, var int data, var int IsF The function returns handle of the Anim8 object. ### `Anim8_Delete` -Deletes an Anim8 object created with `Anim8_New`. +Deletes an Anim8 object created with [`Anim8_New`](#anim8_new). ```dae func void Anim8_Delete(var int handle) ``` **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) ### `Anim8_Get` Get current value of the object. @@ -72,7 +76,7 @@ func int Anim8_Get(var int handle) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) **Return value** @@ -86,7 +90,7 @@ func void Anim8_Set(var int handle, var int value) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae var int value` New value of the object @@ -98,7 +102,7 @@ func int Anim8_Empty(var int handle) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) **Return value** @@ -112,19 +116,19 @@ func void Anim8_RemoveIfEmpty(var int handle, var int on) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae var int on` `TRUE`: enable, `FALSE`: disable ### `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 `#!dae delete(data)` is called if the object is empty. Works only if `Anim8_RemoveIfEmpty` is also activated. +With [`Anim8_NewExt`](#anim8_newext) handler and data can be set. If this function is called with `TRUE`, `data` is taken as a handle and `#!dae delete(data)` is called if the object is empty. Works only if [`Anim8_RemoveIfEmpty`](#anim8_removeifempty) is also activated. ```dae func void Anim8_RemoveDataIfEmpty(var int handle, var int on) ``` **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae var int on` `TRUE`: enable, `FALSE`: disable @@ -136,7 +140,7 @@ func void Anim8(var int handle, var int target, var int span, var int interpol) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae var int target` Target value of this command. When the object's value has reached this value, the command is considered completed and deleted. - `#!dae var int span` @@ -152,7 +156,7 @@ func void Anim8q(var int handle, var int target, var int span, var int interpol) **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae 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. - `#!dae var int span` @@ -161,21 +165,21 @@ func void Anim8q(var int handle, var int target, var int span, var int interpol) What form of movement is used (See [constants](../various/userconstants.md#anim8) for this) ### `Anim8_CallOnRemove` -Registers a function to be called when the object is deleted (e.g. by `Anim8_RemoveIfEmpty`) +Registers a function to be called when the object is deleted (e.g. by [`Anim8_RemoveIfEmpty`](#anim8_removeifempty)) ```dae func void Anim8_CallOnRemove(var int handle, var func dfnc) ``` **Parameters** - `#!dae var int handle` - Handle returned from `Anim8_New` + Handle returned from [`Anim8_New`](#anim8_new) - `#!dae var func dfnc` This function is called when the object is deleted ## Examples ### Count up to a number -Count from 0 to 10 in 10 seconds. We use the `Print_Ext` function from Interface to display the text. +Count from 0 to 10 in 10 seconds. We use the `Print_Ext` function from [Interface](../tools/interface.md) to display the text. ```dae func void Example1() { @@ -206,7 +210,7 @@ func void MyLoop1(var int MyText, var int Number) // As I said, everything is deleted fully automatically }; ``` -A similar example can be found in the Interface examples. +A similar example can be found in the [Interface examples](../tools/interface.md#examples). ### Moving zCVob in loop Now we make a vob constantly move back and forth, but without a mover. [FrameFunctions](../tools/frame_functions.md) are used for the loop: diff --git a/docs/zengin/scripts/extenders/lego/applications/bars.md b/docs/zengin/scripts/extenders/lego/applications/bars.md index 950b7499a1..c007323f7b 100644 --- a/docs/zengin/scripts/extenders/lego/applications/bars.md +++ b/docs/zengin/scripts/extenders/lego/applications/bars.md @@ -1,10 +1,14 @@ +--- +title: Bars +description: LeGo package for creating new status bars +--- # Bars This package makes it very easy to add new bars, for e.g. stamina. ## Dependencies -- PermMem -- View +- [PermMem](../tools/permmem.md) +- [View](../tools/view.md) ## Initialization Initialize with `LeGo_Bars` flag. diff --git a/docs/zengin/scripts/extenders/lego/applications/bars.pl.md b/docs/zengin/scripts/extenders/lego/applications/bars.pl.md index d8bd8df4ef..af683b9162 100644 --- a/docs/zengin/scripts/extenders/lego/applications/bars.pl.md +++ b/docs/zengin/scripts/extenders/lego/applications/bars.pl.md @@ -1,13 +1,14 @@ --- -title: Paski +title: Bars +description: Pakiet LeGo do tworzenia nowych pasków statusu --- # Bars - paski Ten pakiet bardzo ułatwia dodawanie nowych pasków, dla wyświetlania np. wytrzymałości. ## Zależności -- PermMem -- View +- [PermMem](../tools/permmem.md) +- [View](../tools/view.md) ## Inicjalizacja Zainicjuj za pomocą flagi `LeGo_Bars`. diff --git a/docs/zengin/scripts/extenders/lego/applications/bloodsplats.md b/docs/zengin/scripts/extenders/lego/applications/bloodsplats.md index 014b701e51..1ca9bd6cd9 100644 --- a/docs/zengin/scripts/extenders/lego/applications/bloodsplats.md +++ b/docs/zengin/scripts/extenders/lego/applications/bloodsplats.md @@ -1,3 +1,7 @@ +--- +title: Bloodsplats +description: LeGo package for displaying bloodsplats on a screen when player is hit +--- # Bloodsplats 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](http://CGTextures.com). If you use Bloodsplats in your modification, this site must be noted in the credits. @@ -6,8 +10,8 @@ If this package is activated, red blood splatters will appear on the screen when ## Dependencies -- Floats -- View +- [Floats](../../ikarus/floats.md) +- [View](../tools/view.md) - [Random](../tools/random.md) - [Anim8](anim8.md) @@ -36,3 +40,19 @@ Pretty pointless feature that smears the entire screen. ```dae func void Bloodsplats_Rage() ``` + +### `Npc_GetPercFunc` +`oCNpc::GetPerceptionFunc` engine function wrapper +```dae +func int Npc_GetPercFunc(var C_Npc npc, var int type) +``` +**Parameters** + +- `#!dae var C_NPC npc` + NPC whose perception is checked +- `#!dae var int type` + Checked perception type (form [`Constant.d`](https://github.com/VaanaCZ/gothic-2-addon-scripts/blob/Unified-EN/_work/Data/Scripts/Content/_intern/Constants.d#L213-L258)) + +**Return value** + +The function returns the state of NPCs selected perception. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/applications/buffs.md b/docs/zengin/scripts/extenders/lego/applications/buffs.md index ff46616b77..e219fd1c97 100644 --- a/docs/zengin/scripts/extenders/lego/applications/buffs.md +++ b/docs/zengin/scripts/extenders/lego/applications/buffs.md @@ -1,10 +1,14 @@ +--- +title: Buffs +description: LeGo package allowing to create status effects and apply them on NPCs +--- # Buffs 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. ## Dependencies -- PermMem +- [PermMem](../tools/permmem.md) - [FrameFunctions](../tools/frame_functions.md) ## Initialization @@ -39,7 +43,7 @@ func int Buff_Apply(var C_NPC npc, var int buff) The function returns the handle of the buff, which was just generated. ### `Buff_ApplyUnique` -`Buff_Apply`, but nothing happens if a status effect of that kind is already on the NPC. +[`Buff_Apply`](#buff_apply), but nothing happens if a status effect of that kind is already on the NPC. ```dae func int Buff_ApplyUnique(var C_NPC npc, var int buff) ``` @@ -56,7 +60,7 @@ func int Buff_ApplyUnique(var C_NPC npc, var int buff) The function returns the handle of the buff, which was just generated or `0` if the buff is already applied on the NPC. ### `Buff_ApplyOrRefresh` -`Buff_Apply`, but if a status effect of this type is already affecting the NPC, the duration will be reset. +[`Buff_Apply`](#buff_apply), but if a status effect of this type is already affecting the NPC, the duration will be reset. ```dae func int Buff_ApplyOrRefresh(var C_NPC n, var int buff) ``` @@ -84,8 +88,6 @@ func void Buff_Refresh(var int buffHandle) ### `Buff_Remove` Removes the buff from the all NPCs. - -[//]: # (TODO Needs to be checked) ```dae func void Buff_Remove(var int buffHandle) ``` @@ -96,8 +98,6 @@ func void Buff_Remove(var int buffHandle) ### `Buff_RemoveAll` Removes the buffs form the NPC. - -[//]: # (TODO Needs to be checked) ```dae func void Buff_RemoveAll(var C_NPC npc, var int buffInstance) ``` @@ -173,13 +173,13 @@ class lCBuff // Internal, no need to set during instance construction var int _startedTime; - var int _endTime; // Not rendundant with durationMS because buffs can be refreshed + var int _endTime; // Not redundant with durationMS because buffs can be refreshed }; ``` ## Examples -## Delayed poison +### Delayed poison ```dae instance deadly_poison(lCBuff) { diff --git a/docs/zengin/scripts/extenders/lego/applications/buttons.md b/docs/zengin/scripts/extenders/lego/applications/buttons.md new file mode 100644 index 0000000000..d751f86b61 --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/applications/buttons.md @@ -0,0 +1,327 @@ +--- +title: Buttons +description: LeGo package for creating buttons that reacts to mouse +--- +# Buttons +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. + +## Dependencies + +- [PermMem](../tools/permmem.md) +- [View](../tools/view.md) + +## Initialization +Initialize with `LeGo_Buttons` flag. +```dae +LeGo_Init(LeGo_Buttons); +``` + +## Implementation +[:material-github: Buffs.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/Buttons.d) + +## Functions + +### `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)`. +```dae +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) +``` +**Parameters** + +- `#!dae var int posx` + The horizontal position of the button in virtual coordinates +- `#!dae var int posy` + The vertical position of the button in virtual coordinates +- `#!dae var int width` + Width of the button in virtual coordinates +- `#!dae var int height` + Height of the button in virtual coordinates +- `#!dae var string tex` + Name of the button texture +- `#!dae var func on_enter` + This function is called when the mouse enters the button +- `#!dae var func on_leave` + This function is called when the mouse leaves the button +- `#!dae 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. + +### `Button_CreatePxl` +`Button_Create` with pixels instead of virtual coordinates. +```dae +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) +``` +**Parameters** + +- `#!dae var int posx` + The horizontal position of the button in pixels +- `#!dae var int posy` + The vertical position of the button in pixels +- `#!dae var int width` + Width of the button in pixels +- `#!dae var int height` + Height of the button in pixels +- `#!dae var string tex` + Name of the button texture +- `#!dae var func on_enter` + This function is called when the mouse enters the button +- `#!dae var func on_leave` + This function is called when the mouse leaves the button +- `#!dae 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. + +### `Button_Delete` +Completely deletes a button. +```dae +func void Button_Delete(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +### `Button_Show` +Shows the button and makes it respond to the mouse. +```dae +func void Button_Show(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +### `Button_Hide` +Hides the button and disables it, so it is no longer responding to the mouse. +```dae +func void Button_Hide(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +### `Button_SetTexture` +Sets the texture of the button. +```dae +func void Button_SetTexture(var int hndl, var string tex) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var string tex` + Name of the new texture + +### `Button_SetCaption` +Displays a centered text on the button. +```dae +func void Button_SetCaption(var int hndl, var string caption, var string font) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var string caption` + The text to be displayed +- `#!dae var string font` + The font in which the text should be displayed + +### `Button_CreateMouseover` +Attaches a mouseover box to the cursor. +```dae +func void Button_CreateMouseover(var string text, var string font) +``` +**Parameters** + +- `#!dae var string text` + The text in the mouseover box +- `#!dae var string font` + The font of the text + +### `Button_DeleteMouseover` +Deletes the mouseover box. +```dae +func void Button_DeleteMouseover() +``` + +### `Button_Activate` +Activates the button, so it reacts to the mouse. Does not change the visibility. +```dae +func void Button_Activate(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +### `Button_Deactivate` +Disables the button, so it no longer reacts to the mouse. +```dae +func void Button_Deactivate(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +### `Button_SetUserData` +Sets the user data of the button, an integer, to give the button individual information. +```dae +func void Button_SetUserData(var int hndl, var int data) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var int data` + Individual integer of the button (part of the internal `_Button` class) + + +### `Button_GetUserData` +Gets the user data of the button. +```dae +func int Button_GetUserData(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the user data of the button. + + +### `Button_GetState` +Gets the status of the button as a bit field. See [User Constants](../various/userconstants.md#buttons). +```dae +func int Button_GetState(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the status of the button. + + +### `Button_Move` +Moves the button by the given value in pixels. `posx = posx + nposx` +```dae +func void Button_Move(var int hndl, var int nposx, var int nposy) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var int nposx` + X-axis shift in pixels +- `#!dae var int nposy` + Y-axis shift in pixels + +### `Button_MoveVrt` +Moves the button by the given value in virtual coordinates. `posx = posx + nposx` +```dae +func void Button_Move(var int hndl, var int nposx, var int nposy) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var int nposx` + X-axis shift in virtual coordinates +- `#!dae var int nposy` + Y-axis shift in virtual coordinates + +### `Button_MoveTo` +Moves a button to the given position in pixels. `posx = nposx` +```dae +func void Button_MoveVrt(var int hndl, var int nposx, var int nposy) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var int nposx` + New horizontal position in pixels +- `#!dae var int nposy` + New vertical position in pixels + +### `Button_MoveToVrt` +Moves a button to the given position in virtual coordinates. `posx = nvposx` +```dae +func void Button_MoveVrt(var int hndl, var int nvposx, var int nvposy) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` +- `#!dae var int nvposx` + New horizontal position in virtual coordinates +- `#!dae var int nvposy` + New vertical position in virtual coordinates + +### `Button_GetViewHandle` +Returns the button's `zCView` as a handle. +```dae +func int Button_GetViewHandle(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the button's `zCView` as a handle. + +### `Button_GetViewPtr` +Returns the button's `zCView` as a pointer. +```dae +func int Button_GetViewPtr(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the button's `zCView` as a pointer. + +### `Button_GetView` +Returns the button's `zCView` as an object. +```dae +func zCView Button_GetView(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the button's `zCView` as an object. + +### `Button_GetCaptionPtr` +Returns the pointer to the text of the button. +```dae +func int Button_GetCaptionPtr(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle returned from `Button_Create` + +**Return value** + +The function returns the pointer to the text of the button. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/applications/console_commands.md b/docs/zengin/scripts/extenders/lego/applications/console_commands.md index e3c7c3c113..40b3d830ec 100644 --- a/docs/zengin/scripts/extenders/lego/applications/console_commands.md +++ b/docs/zengin/scripts/extenders/lego/applications/console_commands.md @@ -1,9 +1,13 @@ +--- +title: Console Commands +description: LeGo package allowing the registering of new console commands +--- # Console Commands This package allows you to create new console commands. ## Dependencies -- PermMem +- [PermMem](../tools/permmem.md) - [HookEngine](../tools/hook_engine.md) ## Initialization @@ -29,7 +33,7 @@ func void CC_Register(var func f, var string cmdPrefix, var string description) - `#!dae var string cmdPrefix` This is a command, which can be entered in the console. - `#!dae var string description` - This text appears next to the command (in zSpy) when you use the `help` command in the console. + This text appears next to the command (in [zSpy](../../../../tools/zSpy.md)) when you use the `help` command in the console. ### `CC_Remove` Removes a function from the console commands. @@ -58,7 +62,7 @@ The function returns `TRUE` if there is a corresponding function, `FALSE` is ret ## Examples ### Basic command example -As a basic example - let us create a version command, which prints a version of our modification. +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. ```dae const string Mod_Version = "My mod version 0.1alpha"; @@ -78,7 +82,7 @@ We then have to register the functions. For convenience, I created a new `Regist ```dae func void RegisterConsoleFunctions() { - CC_Register (CC_ModVersion, "mod_version", "Version of my amazing mod."); + CC_Register (CC_ModVersion, "version", "Version of my amazing mod."); }; ``` Lastly, we have to call this function from `INIT_GLOBAL` function. diff --git a/docs/zengin/scripts/extenders/lego/applications/console_commands.pl.md b/docs/zengin/scripts/extenders/lego/applications/console_commands.pl.md index 21293aa12c..aaf30badd8 100644 --- a/docs/zengin/scripts/extenders/lego/applications/console_commands.pl.md +++ b/docs/zengin/scripts/extenders/lego/applications/console_commands.pl.md @@ -1,12 +1,13 @@ --- -title: Polecenia konsoli +title: Console Commands +description: Pakiet LeGo umożliwiający rejestrację nowych poleceń konsoli --- # Console Commands - polecenia konsoli Ten Pakiet pozwala na tworzenie nowych poleceń konsoli dostępnej po naciśnięciu klawisza F2 w trybie marvin. ## Zależności -- PermMem +- [PermMem](../tools/permmem.md) - [HookEngine](../tools/hook_engine.md) ## Inicjalizacja @@ -32,7 +33,7 @@ func void CC_Register(var func f, var string cmdPrefix, var string description) - `#!dae var string cmdPrefix` Jest to polecenie, które można wprowadzić w konsoli. - `#!dae var string description` - Ten tekst pojawia się obok polecenia (w zSpy), gdy używasz polecenia `help` w konsoli. + Ten tekst pojawia się obok polecenia (w [zSpy](../../../../tools/zSpy.md)), gdy używasz polecenia `help` w konsoli. ### `CC_Remove` Usuwa funkcje z konsoli komend. @@ -61,7 +62,7 @@ Funkcja zwraca `TRUE` jeśli znajdzie odpowiednią funkcję, inaczej `FALSE`. ## Przykłady ### Proste polecenie konsoli -Jako prosty przykład stwórzmy polecenie version, które wyświetli nam wersję modyfikacji. +Jako prosty przykład stwórzmy polecenie **version**, które wyświetli nam wersję modyfikacji. Po pierwsze, deklarujemy stałą zmienną `string` do przechowywania informacji o wersji. ```dae const string Mod_Version = "Wersja modyfikacji - 0.1alpha"; @@ -69,7 +70,7 @@ const string Mod_Version = "Wersja modyfikacji - 0.1alpha"; Następnie tworzymy nową funkcję. !!! Note - Zwróć uwagę na poprawną sygnaturę funkcji. Jeśli nie będzie błędna, polecenie spowoduje awarię gry. + Zwróć uwagę na poprawną sygnaturę funkcji. Jeśli będzie ona błędna, polecenie spowoduje awarię gry. ```dae // Ta funkcja jest wywoływana przez nasze nowe polecenie @@ -82,7 +83,7 @@ Następnie musimy zarejestrować polecenie. Dla wygody stworzyłem nową funkcj ```dae func void RegisterConsoleFunctions() { - CC_Register (CC_ModVersion, "wersja_moda", "Wersja mojej modyfikacji."); + CC_Register (CC_ModVersion, "version", "Wersja mojej modyfikacji."); }; ``` Na koniec musimy wywołać tę funkcję w `INIT_GLOBAL`. diff --git a/docs/zengin/scripts/extenders/lego/applications/cursor.md b/docs/zengin/scripts/extenders/lego/applications/cursor.md index 4be94167d0..b9894118d0 100644 --- a/docs/zengin/scripts/extenders/lego/applications/cursor.md +++ b/docs/zengin/scripts/extenders/lego/applications/cursor.md @@ -1,3 +1,7 @@ +--- +title: Cursor +description: LeGo package implementing in-game mouse cursor support +--- # Cursor 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](../various/userconstants.md#cursor-1). @@ -7,9 +11,9 @@ This package implements Gothic in-game mouse cursor support. To visually display ## Dependencies -- Floats +- [Floats](../../ikarus/floats.md) - [FrameFunctions](../tools/frame_functions.md) -- View +- [View](../tools/view.md) ## Initialization Initialize with `LeGo_Cursor` flag. @@ -115,7 +119,7 @@ func void Button_Click() }; ``` -This also can be done by the Buttons package instead of View. +This also can be done by the Buttons package instead of [View](../tools/view.md). ### Event handler Since LeGo 2.2 there is also an event handler (`#!dae var int Cursor_Event`) in the cursor package. This example briefly explains how it works: diff --git a/docs/zengin/scripts/extenders/lego/applications/dialoggestures.md b/docs/zengin/scripts/extenders/lego/applications/dialoggestures.md index 7ea06ea9f4..402e2f8699 100644 --- a/docs/zengin/scripts/extenders/lego/applications/dialoggestures.md +++ b/docs/zengin/scripts/extenders/lego/applications/dialoggestures.md @@ -1,3 +1,7 @@ +--- +title: Dialoggestures +description: LeGo package for modifying the NPCs' gestures during dialogue +--- # Dialoggestures This package can modify the NPCs' gestures during dialogue to better bring out emotions. diff --git a/docs/zengin/scripts/extenders/lego/applications/focusnames.md b/docs/zengin/scripts/extenders/lego/applications/focusnames.md index fcce604ba2..91e4940938 100644 --- a/docs/zengin/scripts/extenders/lego/applications/focusnames.md +++ b/docs/zengin/scripts/extenders/lego/applications/focusnames.md @@ -1,9 +1,13 @@ +--- +title: Focusnames +description: LeGo package that change NPCs/Object's focus name color based on its attitude +--- # Focusnames 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) ## Dependencies -- Interface +- [Interface](../tools/interface.md) - [HookEngine](../tools/hook_engine.md) ## Initialization @@ -16,7 +20,7 @@ LeGo_Init(LeGo_Focusnames); [:material-github: Focusnames.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/Focusnames.d) ## Usage -If you want to change colors for any behavior edit the following functions directly in `Focusnames.d` file. +If you want to change colors for any behavior edit the following functions directly in [`Focusnames.d`](https://github.com/Lehona/LeGo/blob/dev/Focusnames.d) file. ### `Focusnames_Color_Friendly` ```dae diff --git a/docs/zengin/scripts/extenders/lego/applications/gamestate.md b/docs/zengin/scripts/extenders/lego/applications/gamestate.md index 8875b5bc5d..00fe81bad6 100644 --- a/docs/zengin/scripts/extenders/lego/applications/gamestate.md +++ b/docs/zengin/scripts/extenders/lego/applications/gamestate.md @@ -1,3 +1,7 @@ +--- +title: Gamestate +description: LeGo package for calling functions during different game states +--- # Gamestate Gamestate package allows to check for different game states (game start, game load or level change). @@ -65,8 +69,6 @@ func void Init_Global() }; ``` -This might be useful when working with PermMem, where PermMem objects do not need to be recreated after the game loads. - It can also be done like that: ```dae func void Init_Global() diff --git a/docs/zengin/scripts/extenders/lego/applications/gamestate.pl.md b/docs/zengin/scripts/extenders/lego/applications/gamestate.pl.md index e8c99e7377..372894133f 100644 --- a/docs/zengin/scripts/extenders/lego/applications/gamestate.pl.md +++ b/docs/zengin/scripts/extenders/lego/applications/gamestate.pl.md @@ -1,5 +1,6 @@ --- -title: Stan gry +title: Gamestate +description: Pakiet LeGo do wywoływania funkcji podczas różnych stanów gry --- # Gamestate - stan gry Pakiet Gamestate pozwala sprawdzić stan gry (rozpoczęcie gry, ładowanie gry lub zmiana poziomu). @@ -41,7 +42,7 @@ func void Gamestate_RemoveListener(var func listener) ## Przykłady Istnieją teraz dwie możliwości. Wszystko można zrobić bezpośrednio w `Init_Global` lub za pomocą [EventHandler](../tools/event_handler.md). -### `Init_Global` +### Init_Global ```dae func void Init_Global() { @@ -68,8 +69,6 @@ func void Init_Global() }; ``` -Może to być przydatne podczas pracy z PermMem, gdzie obiekty PermMem nie muszą być odtwarzane po załadowaniu gry. - Można to również zrobić tak: ```dae func void Init_Global() @@ -98,7 +97,7 @@ func void Init_Global() }; ``` -### EventHandler - obsługa zdarzeń +### EventHandler ```dae func void Init_Global() { diff --git a/docs/zengin/scripts/extenders/lego/applications/names.md b/docs/zengin/scripts/extenders/lego/applications/names.md index 750919ed46..be3f0ae7d9 100644 --- a/docs/zengin/scripts/extenders/lego/applications/names.md +++ b/docs/zengin/scripts/extenders/lego/applications/names.md @@ -1,8 +1,12 @@ +--- +title: Names +description: LeGo package for changing NPCs display name during the game +--- # Names Allows the user to change NPC name e.g. after he shows up. ## Dependencies -N/A +- [Talents](../tools/talents.md) ## Initialization N/A diff --git a/docs/zengin/scripts/extenders/lego/applications/render.md b/docs/zengin/scripts/extenders/lego/applications/render.md index c0b8eba391..432bfd3af2 100644 --- a/docs/zengin/scripts/extenders/lego/applications/render.md +++ b/docs/zengin/scripts/extenders/lego/applications/render.md @@ -1,10 +1,14 @@ +--- +title: Render +description: LeGo package for rendering items on a screen +--- # Render 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. ## Dependencies -- List -- View -- PermMem +- [List](../tools/list.md) +- [View](../tools/view.md) +- [PermMem](../tools/permmem.md) ## Initialization Initialize with `LeGo_Render` flag. diff --git a/docs/zengin/scripts/extenders/lego/applications/saves.md b/docs/zengin/scripts/extenders/lego/applications/saves.md index 2c3e245fe4..d0c95ea4eb 100644 --- a/docs/zengin/scripts/extenders/lego/applications/saves.md +++ b/docs/zengin/scripts/extenders/lego/applications/saves.md @@ -1,5 +1,9 @@ +--- +title: Saves +description: LeGo package offering open data stream to the game save file +--- # Saves -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. +Offers an open file stream that can read/write variables on save/load. It is used by [PermMem](../tools/permmem.md), so you don't need to address it manually anymore. ## Dependencies @@ -17,13 +21,13 @@ LeGo_Init(LeGo_Saves); ## Functions ### `BW_Savegame` -Custom function. It creates a stream to its own memory file, this can be filled with the `BW_*` functions from the [BinaryMachines](../tools/binary_machines.md). +Custom function. It creates a stream to its own memory file, this can be filled with the `BW_*` functions from the [BinaryMachines](../tools/binary_machines.md#binarywriter). ```dae func void BW_Savegame() ``` ### `BR_Savegame` -Custom function. It opens a stream to a previously saved memory file, which can be read from the [BinaryMachines](../tools/binary_machines.md) using the `BR_*` functions. +Custom function. It opens a stream to a previously saved memory file, which can be read from the [BinaryMachines](../tools/binary_machines.md#binaryreader) using the `BR_*` functions. ```dae func void BR_Savegame() ``` diff --git a/docs/zengin/scripts/extenders/lego/applications/trialoge.md b/docs/zengin/scripts/extenders/lego/applications/trialoge.md index c6372ce80c..27bbb993cf 100644 --- a/docs/zengin/scripts/extenders/lego/applications/trialoge.md +++ b/docs/zengin/scripts/extenders/lego/applications/trialoge.md @@ -1,3 +1,7 @@ +--- +title: Trialoge +description: LeGo package implementing trialogues to gothic +--- # Trialoge This package allows you to create conversations with any number of NPCs and control the camera during the dialog. @@ -16,7 +20,7 @@ LeGo_Init(LeGo_Trialoge); ## Functions ### `EquipWeapon` -Sektenspinner's function. (Taken from the forum.) +Sektenspinner's function. Makes NPC equip a weapon. ```dae func void EquipWeapon(var C_NPC slf, var int ItemInstance) ``` @@ -25,7 +29,16 @@ func void EquipWeapon(var C_NPC slf, var int ItemInstance) - `#!dae var C_NPC slf` NPC to have a weapon equipped - `#!dae var int ItemInstance` - Weapon instance to be equipped + Weapon instance ID to be equipped + +**Configuration** + +`#!dae 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 ### `Npc_GetArmor` Returns NPC's equipped armor. @@ -53,7 +66,36 @@ func int Npc_GetMeleeWeapon(var C_NPC slf) **Return value** -The function returns instance of melee weapon equipped by the NPC. +The function returns instance ID of melee weapon equipped by the NPC. + +### `Npc_GetRangedWeapon` +Returns NPC's equipped ranged weapon. +```dae +func int Npc_GetRangedWeapon(var c_npc slf) +``` +**Parameters** + +- `#!dae var C_NPC slf` + NPC to get the weapon from + +**Return value** + +The function returns instance ID of ranged weapon equipped by the NPC. + +### `Npc_TradeItem` +Swaps NPCs equipped weapon. +```dae +func void Npc_TradeItem(var c_npc slf, var int itm0, var int itm1) +``` +**Parameters** + +- `#!dae var C_NPC slf` + NPC to perform operation on +- `#!dae var int itm0` + instance ID of item to remove +- `#!dae var int itm1` + instance ID of item to create and equip + ### `DiaCAM_Update` Sektenspinner's function that updates the dialogue camera. (Used internally.) diff --git a/docs/zengin/scripts/extenders/lego/applications/trialoge.pl.md b/docs/zengin/scripts/extenders/lego/applications/trialoge.pl.md index 1d2f4f56fe..57bb2fc502 100644 --- a/docs/zengin/scripts/extenders/lego/applications/trialoge.pl.md +++ b/docs/zengin/scripts/extenders/lego/applications/trialoge.pl.md @@ -1,3 +1,7 @@ +--- +title: Trialoge +description: Pakiet LeGo implementujący trialogi w gothicu +--- # Trialogi Ten pakiet pozwala na tworzenie rozmów z dowolną liczbą NPC i sterowanie kamerą podczas dialogu. @@ -16,7 +20,7 @@ LeGo_Init(LeGo_Trialoge); ## Funkcje ### `EquipWeapon` -Funkcja Sektenspinnera. (wzięta z forum) +Funkcja Sektenspinnera. Sprawia, że NPC wyposaża broń. ```dae func void EquipWeapon(var C_NPC slf, var int ItemInstance) ``` @@ -27,6 +31,15 @@ func void EquipWeapon(var C_NPC slf, var int ItemInstance) - `#!dae var int ItemInstance` Instancja broni do wyposażenia +**Konfiguracja** + +`#!dae const int EquipWeapon_TogglesEquip = 1` + +Powyższa stała ustala zachowanie funkcji podczas próby założenia już założonej broni: + +- `0` - `EquipWeapon` nic nie zrobi +- `1` - `EquipWeapon` zdejmie tą broń + ### `Npc_GetArmor` Pobiera pancerz wyposażony przez NPC. ```dae @@ -39,7 +52,7 @@ func int Npc_GetArmor(var C_NPC slf) **Zwracana wartość** -Funkcja zwraca instancje pancerza założonego przez NPC. +Funkcja zwraca ID instancji pancerza założonego przez NPC. ### `Npc_GetMeleeWeapon` Pobiera wyposażoną przez NPC broń białą. @@ -53,7 +66,35 @@ func int Npc_GetMeleeWeapon(var C_NPC slf) **Zwracana wartość** -Funkcja zwraca instancje broni białej wyposażonej przez NPC. +Funkcja zwraca ID instancji broni białej wyposażonej przez NPC. + +### `Npc_GetRangedWeapon` +Pobiera wyposażoną przez NPC broń dystansową. +```dae +func int Npc_GetRangedWeapon(var C_NPC slf) +``` +**Parametry** + +- `#!dae var C_NPC slf` + NPC którego broń jest pobierana + +**Zwracana wartość** + +Funkcja zwraca ID instancji broni dystansowej wyposażonej przez NPC. + +### `Npc_TradeItem` +Podmienia broń założoną przez NPC. +```dae +func void Npc_TradeItem(var c_npc slf, var int itm0, var int itm1) +``` +**Parametry** + +- `#!dae var C_NPC slf` + NPC na którym wykonywana jest operacja +- `#!dae var int itm0` + ID instancji przedmiotu do usunięcia +- `#!dae var int itm1` + ID instancji przedmiotu do stworzenia i założenia ### `DiaCAM_Update` Funkcja Sektenspinnera. Aktualizuje kamerę dialogową. (Używana wewnętrznie) @@ -73,7 +114,7 @@ Resetuje kamery dialogowe do ustawień domyślnych. func void DiaCAM_Enable() ``` ### `TRIA_Wait` -Makes `self` and `other` wait for each other, e.g. for `AI_GotoWP` actions for synchronization. +Sprawia że `self` i `other` czekają na siebie, np. podczas dla synchronizacji po wywołaniu `AI_GotoWP`. ```dae func void TRIA_Wait() ``` @@ -101,7 +142,7 @@ func void TRIA_Barrier() ``` ### `TRIA_Next` -Ustawia podanego npc na `self`. +Ustawia podanego NPC na `self`. ```dae func void TRIA_Next(var C_NPC n0) ``` @@ -118,7 +159,7 @@ func void TRIA_Cam(var string evt) **Parametry** - `#!dae var string evt` - Nazwa ruchu kamery w Spacerze. Jeśli zostanie przekazany pusty łańcuch znaków, nastąpi przerwanie ruchu kamery. + Nazwa ruchu kamery w Spacerze. Jeśli zostanie przekazany pusty ciąg znaków, nastąpi przerwanie ruchu kamery. ### `TRIA_Finish` Kończy trwający trialog. Musi być zawsze wywoływana na końcu, w przeciwnym razie dalsze trialogi nie będą mogły zostać rozpoczęte. @@ -126,10 +167,10 @@ Kończy trwający trialog. Musi być zawsze wywoływana na końcu, w przeciwnym func void TRIA_Finish() ``` -## Examples +## Przykłady -### A Simple Trialogue -The following conversation is resolved via the trialogues: +### Prosty Trialog +Poniższa konwersacja zostanie zaimplementowana za pomocą trialogów: 1. **Arto:** Wybacz bohaterze, ale nie możesz tędy przejść. 2. **Bohater:** Dlaczego nie? @@ -230,4 +271,4 @@ func void TRIA_Test_info() }; ``` !!! Note - In addition, here are still [Dialoggestures](dialoggestures.md) used. + Dodatkowo w powyższym przykładzie użyty jest też pakiet [Dialoggestures](dialoggestures.md). diff --git a/docs/zengin/scripts/extenders/lego/tools/LeGo_tools.d b/docs/zengin/scripts/extenders/lego/tools/LeGo_tools.d new file mode 100644 index 0000000000..e0802d8232 --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/LeGo_tools.d @@ -0,0 +1,2001 @@ +// ========================================================= +// +// AI_Function +// +// ========================================================= + +/// Queues the `function` to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +func void AI_Function(var C_NPC slf, var func function) {}; + +/// Queues the `function` with an integer parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param Integer parameter for the function +func void AI_Function_I(var C_NPC slf, var func function, var int param) {}; + +/// Queues the `function` with an NPC instance parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param NPC instance parameter for the function +func void AI_Function_N(var C_NPC slf, var func function, var int param) {}; + +/// Queues the `function` with a string parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param String parameter for the function +func void AI_Function_S(var C_NPC slf, var func function, var string param) {}; + +/// Queues the `function` with two integer parameters to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 First integer parameter for the function +/// @param param2 Second integer parameter for the function +func void AI_Function_II(var C_NPC slf, var func function, var int param1, var int param2) {}; + +/// Queues the `function` with two NPC instance parameters to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 First NPC instance parameter for the function +/// @param param2 Second NPC instance parameter for the function +func void AI_Function_NN(var C_NPC slf, var func function, var int param1, var int param2) {}; + +/// Queues the `function` with two string parameters to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 First string parameter for the function +/// @param param2 Second string parameter for the function +func void AI_Function_SS(var C_NPC slf, var func function, var string param1, var string param2) {}; + +/// Queues the `function` with an integer and a string parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 Integer parameter for the function +/// @param param2 String parameter for the function +func void AI_Function_IS(var C_NPC slf, var func function, var int param1, var string param2) {}; + +/// Queues the `function` with a string and an integer parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 String parameter for the function +/// @param param2 Integer parameter for the function +func void AI_Function_SI(var C_NPC slf, var func function, var string param1, var int param2) {}; + +/// Queues the `function` with an NPC instance and a string parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 NPC instance parameter for the function +/// @param param2 String parameter for the function +func void AI_Function_NS(var C_NPC slf, var func function, var int param1, var string param2) {}; + +/// Queues the `function` with a string and an NPC instance parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 String parameter for the function +/// @param param2 NPC instance parameter for the function +func void AI_Function_SN(var C_NPC slf, var func function, var string param1, var int param2) {}; + +/// Queues the `function` with an integer and an NPC instance parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 Integer parameter for the function +/// @param param2 NPC instance parameter for the function +func void AI_Function_IN(var C_NPC slf, var func function, var int param1, var int param2) {}; + +/// Queues the `function` with an NPC instance and an integer parameter to be called with a delay in the AI queue of `slf`. +/// +/// @param slf NPC in whose AI queue the function is queued +/// @param function Name of the function to be queued +/// @param param1 NPC instance parameter for the function +/// @param param2 Integer parameter for the function +func void AI_Function_NI(var C_NPC slf, var func function, var int param1, var int param2) {}; + +// ========================================================= +// +// BinaryMachines +// +// ========================================================= + +/// Creates the file with the specified `file` name and opens a stream. Fails if a stream is already open. +/// +/// @param file Name of the created file +/// @return Returns TRUE if the file is successfully created and initialized; otherwise, FALSE. +func int BW_NewFile(var string file) {}; + +/// Closes the current write stream. +func void BW_Close() {}; + +/// Writes `length` bytes from `data` to the stream, up to a maximum of 4 bytes. +/// +/// @param data Value of bytes +/// @param length Number of bytes +func void BW(var int data, var int length) {}; + +/// Writes 4 bytes from `data` to the stream, equivalent to `BW(data, 4)`. +/// +/// @param data Integer value to write +func void BW_Int(var int data) {}; + +/// Writes the first character from `data` to the stream, equivalent to `BW(Str_GetCharAt(data, 0), 1)`. +/// +/// @param data Char to write +func void BW_Char(var string data) {}; + +/// Writes `data` terminated with '\0' to the stream. +/// +/// @param data String to write +func void BW_String(var string data) {}; + +/// Writes a byte from `data` to the stream, equivalent to `BW(data, 1)`. +/// +/// @param data Byte value to write +func void BW_Byte(var int data) {}; + +/// Writes `length` of bytes from the pointer `dataPtr` to the stream. +/// +/// @param dataPtr Pointer to the data to write +/// @param length Number of bytes +func void BW_Bytes(var int dataPtr, var int length) {}; + +/// Writes the string `data` to the stream without terminating it, making it unreadable. +/// +/// @param data Text to write +func void BW_Text(var string data) {}; + +/// Writes a paragraph to the stream. +func void BW_NextLine() {}; + +/// Opens the file with the specified `file` name and opens a stream. Fails if a stream is already open. +/// +/// @param file File to be opened +/// @return Returns TRUE if the file is successfully opened and initialized; otherwise, FALSE. +func int BR_OpenFile(var string file) {}; + +/// Closes the current read stream. +func void BR_Close() {}; + +/// Reads bytes from the stream, up to a maximum of 4 bytes. +/// +/// @param length Number of bytes to read +/// @return Returns the value of read bytes +func int BR(var int length) {}; + +/// Reads 4 bytes from the stream, equivalent to `BR(4)`. +/// +/// @return Returns the read integer +func int BR_Int() {}; + +/// Reads a character from the stream, equivalent to `BR(1)`. +/// +/// @return Returns the read character as a string +func string BR_Char() {}; + +/// Reads a string terminated by '\0' from the stream. +/// +/// @return Returns the read string +func string BR_String() {}; + +/// Reads a byte from the stream. +/// +/// @return Returns the read byte +func int BR_Byte() {}; + +/// Reads bytes from the stream. +/// +/// @param length Number of bytes to read +/// @return Returns a pointer to the read bytes +func int BR_Bytes(var int length) {}; + +/// Reads a line from the stream. +/// +/// @return Returns the read line +func string BR_TextLine() {}; + +/// Reads a string of the given `length` from the stream. +/// +/// @param length Number of characters to read +/// @return Returns the read string +func string BR_Text(var int length) {}; + +/// Changes the read position to the next paragraph created with `BW_NextLine`. +func void BR_NextLine() {}; + +// ========================================================= +// +// EventHandler +// +// ========================================================= + +/// Creates a new event and returns a handle to it. +/// +/// @return The function returns a new PermMem handle to an event. +func int Event_Create() {}; + +/// Alias to PermMem `delete`. Cleans up the handle. +/// +/// @param event Handle returned from `Event_Create` +func void Event_Delete(var int event) {}; + +/// Checks whether the event is "empty," i.e., nothing will happen after its execution. +/// +/// @param event Handle returned from `Event_Create` +/// @return The function returns TRUE if the event is empty; otherwise, FALSE. +func int Event_Empty(var int event) {}; + +/// Checks if `function` is added to the event. +/// +/// @param event Handle returned from `Event_Create` +/// @param function Checked function +/// @return The function returns TRUE if the function is added; otherwise, FALSE. +func int Event_Has(var int event, var func function) {}; + +/// Adds an event handler function. The handler is called after running `Event_Execute`. +/// +/// @param event Handle returned from `Event_Create` +/// @param function Function to be added +func void Event_Add(var int event, var func function) {}; + +/// `Event_Add` but checks if the handler function is already added to prevent duplicates. +/// +/// @param event Handle returned from `Event_Create` +/// @param function Function to be added +func void Event_AddOnce(var int event, var func function) {}; + +/// Removes the event handler `function` from the event. +/// +/// @param event Handle returned from `Event_Create` +/// @param function Function to be removed +func void Event_Remove(var int event, var func function) {}; + +/// Core of the package. Calls all functions registered via `Event_Add` and `Event_AddOnce`. +/// +/// @param event Handle returned from `Event_Create` +/// @param data Int parameter passed to all executed functions +func void Event_Execute(var int event, var int data) {}; + +/// Creates a new event and returns a pointer to it. +/// +/// @return The function returns a new PermMem pointer to an event. +func int EventPtr_Create() {}; + +/// Alias to PermMem `free`. Cleans up the pointer. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +func void EventPtr_Delete(var int eventPtr) {}; + +/// Checks whether the event is "empty," i.e., nothing will happen after its execution. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @return The function returns TRUE if empty; otherwise, FALSE. +func int EventPtr_Empty(var int eventPtr) {}; + +/// Checks if `function` is added to an event. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param function Checked function +/// @return The function returns TRUE if the function is added; otherwise, FALSE. +func int EventPtr_Has(var int eventPtr, var func function) {}; + +/// `EventPtr_Has` but with function ID instead of a pointer. Used mainly internally. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param id ID of the checked function +/// @return The function returns TRUE if the function is added; otherwise, FALSE. +func int EventPtr_HasI(var int eventPtr, var int id) {}; + +/// Adds an event handler function. The handler is called after running `EventPtr_Execute`. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param function Function to be added +func void EventPtr_Add(var int eventPtr, var func function) {}; + +/// `EventPtr_Add` but checks if the handler function is already added to prevent duplicates. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param function Function to be added +func void EventPtr_AddOnce(var int eventPtr, var func function) {}; + +/// `EventPtr_AddI` but checks if the handler function is already added to prevent duplicates. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param id ID of function to be added +func void EventPtr_AddOnceI(var int eventPtr, var int id) {}; + +/// Removes a function from the event's call list. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param function Function to be removed +func void EventPtr_Remove(var int eventPtr, var func function) {}; + +/// `EventPtr_RemoveI` but with function ID instead of a pointer. Used mainly internally. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param id ID of function to be removed +func void EventPtr_RemoveI(var int eventPtr, var int id) {}; + +/// Core of the package. Calls all functions registered via `EventPtr_Add` and `EventPtr_AddOnce`. +/// +/// @param eventPtr Pointer returned from `EventPtr_Create` +/// @param data Int parameter passed to all executed functions +func void EventPtr_Execute(var int eventPtr, var int data) {}; + +// ========================================================= +// +// FrameFunctions +// +// ========================================================= + +/// Adds the Daedalus function FF_Apply to the running FrameFunctions list. FF_Apply is called each frame. +/// +/// @param function Name of the function +func void FF_Apply(var func function) {}; + +/// Adds the Daedalus function FF_ApplyGT to the running FrameFunctions list. FF_ApplyGT is called every frame except when the game is paused. +/// +/// @param function Name of the function +func void FF_ApplyGT(var func function) {}; + +/// Adds the Daedalus function FF_ApplyData to the running FrameFunctions list. The integer parameter data is passed to the function FF_ApplyData. +/// +/// @param function Name of the function. +/// @param data Value passed to the function as a parameter +func void FF_ApplyData(var func function, var int data) {}; + +/// Adds the Daedalus function FF_ApplyExt to the running FrameFunctions list. The function FF_ApplyExt is called every delay milliseconds, and it runs only cycles number of times. +/// +/// @param function Name of the function +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +func void FF_ApplyExt(var func function, var int delay, var int cycles) {}; + +/// Adds the Daedalus function FF_ApplyExtGT to the running FrameFunctions list. The function FF_ApplyExtGT is called every delay milliseconds, and it runs only cycles number of times. Gets called only when the game is not paused. +/// +/// @param function Name of the function +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +func void FF_ApplyExtGT(var func function, var int delay, var int cycles) {}; + +/// Adds the Daedalus function FF_ApplyExtData to the running FrameFunctions list. The function FF_ApplyExtData is called every delay milliseconds, and it runs only cycles number of times. The integer parameter data is passed to the function FF_ApplyExtData. +/// +/// @param function Name of the function. +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +/// @param data Value passed to the function as a parameter +func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data) {}; + +/// Adds the Daedalus function FF_ApplyExtDataGT to the running FrameFunctions list. The function FF_ApplyExtDataGT is called every delay milliseconds, and it runs only cycles number of times. The integer parameter data is passed to the function FF_ApplyExtDataGT. Gets called only when the game is not paused. +/// +/// @param function Name of the function. +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +/// @param data Value passed to the function as a parameter +func void FF_ApplyExtDataGT(var func function, var int delay, var int cycles, var int data) {}; + +/// Alias to FF_Apply, which only adds the function once, even after multiple calls. +/// +/// @param function Name of the function +func void FF_ApplyOnce(var func function) {}; + +/// Alias to FF_ApplyGT, which only adds the function once, even after multiple calls. Loop doesn't run if the game is paused. +/// +/// @param function Name of the function. +func void FF_ApplyOnceGT(var func function) {}; + +/// Alias to FF_ApplyData, which only adds the function with the specified parameter once, even after multiple calls. +/// +/// @param function Name of the function. +/// @param data Value passed to the function as a parameter +func void FF_ApplyOnceData(var func function, var int data) {}; + +/// Alias to FF_ApplyExt, which adds the function only once, after repeated calls. +/// +/// @param function Name of the function +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +func void FF_ApplyOnceExt(var func function, var int delay, var int cycles) {}; + +/// Alias to FF_ApplyExtGT, which adds the function only once after repeated calls. Loop doesn't run if the game is paused. +/// +/// @param function Name of the function +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +func void FF_ApplyOnceExtGT(var func function, var int delay, var int cycles) {}; + +/// Alias to FF_ApplyExtData, which adds the function with the specified parameter only once, after repeated calls. +/// +/// @param function Name of the function +/// @param delay Delay between calls in milliseconds (0 = every frame) +/// @param cycles How many times should the function be called (-1 = endless) +/// @param data Value passed to the function as a parameter +func void FF_ApplyOnceExtData(var func function, var int delay, var int cycles, var int data) {}; + +/// Checks whether the function is active. +/// +/// @param function Name of the function +/// @return The function returns TRUE if the function is active; otherwise, FALSE. +func int FF_Active(var func function) {}; + +/// Checks whether the function with the specified data is active. +/// +/// @param function Name of the function +/// @param data Value previously passed to the function +/// @return The function returns TRUE if the function is active; otherwise, FALSE. +func int FF_ActiveData(var func function, var int data) {}; + +/// Stops a specific FrameFunction. +/// +/// @param function Name of the stopped function +func void FF_Remove(var func function) {}; + +/// Stops all instances of a specific FrameFunction. +/// +/// @param function Name of the stopped function +func void FF_RemoveAll(var func function) {}; + +/// Stops a specific FrameFunction, with the specified value (see FF_ApplyExtData). +/// +/// @param function Name of the stopped function +/// @param data Value previously passed to the function as a parameter +func void FF_RemoveData(var func function, var int data) {}; + +// ========================================================= +// +// Hashtables +// +// ========================================================= + +/// Generates a hashtable of the specified size. +/// +/// @param size Size of the hashtable to be created +/// @return A handle to the created hashtable. +func int HT_CreateSized(var int size) {}; + +/// Generates a standard size hashtable. +/// +/// @return A handle to the created hashtable. +func int HT_Create() {}; + +/// Inserts a value into the Hashtable. +/// +/// @param handle Handle of a hashtable +/// @param val The value to be inserted +/// @param key The key associated with the value +func void HT_Insert(var int handle, var int val, var int key) {}; + +/// Changes the size of the hashtable (usually not necessary as it happens automatically). +/// +/// @param handle Handle of a hashtable +/// @param size The new size of the hashtable +func void HT_Resize(var int handle, var int size) {}; + +/// Reads a value from the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param key The key whose value is to be read +/// @return The value associated with the key. +func int HT_Get(var int handle, var int key) {}; + +/// Checks if the key already exists in the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param key The key to be checked +/// @return TRUE if the key exists, FALSE otherwise. +func int HT_Has(var int handle, var int key) {}; + +/// Removes a key from the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param key The key to be removed +func void HT_Remove(var int handle, var int key) {}; + +/// Changes the value of a key already existing in the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param val The new value +/// @param key The key whose value is to be changed +func void HT_Change(var int handle, var int val, var int key) {}; + +/// Inserts a value into the Hashtable, or changes the value if the key already exists in the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param val The new value +/// @param key The key whose value is to be changed or associated with the value. +func void HT_InsertOrChange(var int handle, var int val, var int key) {}; + +/// Returns the number of entries in a hashtable. +/// +/// @param handle Handle of a hashtable +/// @return The number of entries in the hashtable. +func int HT_GetNumber(var int handle) {}; + +/// Performs a function for each value pair in the hashtable. +/// +/// @param handle Handle of a hashtable +/// @param fnc A function with signature void (int key, int val) +func void HT_ForEach(var int handle, var func fnc) {}; + +/// Deletes the hashtable. +/// +/// @param handle The handle of the hashtable to be deleted +func void HT_Destroy(var int handle) {}; + +// ========================================================= +// +// HookDaedalus +// +// ========================================================= + +/// Hooks the function. +/// +/// @param hooked Hooked function +/// @param hook Hook function +func void HookDaedalusFunc(var func hooked, var func hook) {}; + +/// Alias to the HookDaedalusFunc function. +/// +/// @param hooked Hooked function +/// @param hook Hook function +func void HookDaedalusFuncF(var func hooked, var func hook) {}; + +/// Hooks a function by its ID. +/// +/// @param hookedID ID of hooked function +/// @param hookID ID of hook function +func void HookDaedalusFuncI(var int hookedID, var int hookID) {}; + +/// Hooks a function by its name. +/// +/// @param hookedName Name of hooked function +/// @param hookName Name of hook function +func void HookDaedalusFuncS(var string hookedName, var string hookName) {}; + +/// Checks whether a function is already hooking another. +/// +/// @param funcID Symbol index of a hook function +/// @return TRUE if the function is already hooking another, FALSE otherwise. +func int IsHookD(var int funcID) {}; + +/// Continues the program run with the original function. +func void ContinueCall() {}; + +/// Passes an integer as an argument to the original function. Must be called before ContinueCall. +/// +/// @param i Integer argument to forward +func void PassArgumentI(var int i) {}; + +/// Passes a string as an argument to the original function. Must be called before ContinueCall. +/// +/// @param s String argument to forward +func void PassArgumentS(var string s) {}; + +/// Passes an instance as an argument to the original function. Must be called before ContinueCall. +/// +/// @param n Instance argument to forward +func void PassArgumentN(var instance n) {}; + +// ========================================================= +// +// HookEngine +// +// ========================================================= + +/// Attaches a function to an engine function address. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param function Name of Daedalus function to be called. +func void HookEngine(var int address, var int oldInstr, var string function) {}; + +/// Alias to the HookEngine function. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param function Name of Daedalus function to be called. +func void HookEngineS(var int address, var int oldInstr, var string function) {}; + +/// Alias to HookEngine with funcID. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param funcID ID of Daedalus function to be called. +func void HookEngineI(var int address, var int oldInstr, var int funcID) {}; + +/// Alias to HookEngine with func parameter. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param function Daedalus function to be called. +func void HookEngineF(var int address, var int oldInstr, var func function) {}; + +/// Checks if a hook is already present at a given address. +/// +/// @param address Address of an engine function. +/// @return TRUE if the hook already exists at the address, FALSE otherwise. +func var int IsHooked(var int address) {}; + +/// Checks if a hook with a certain function is already present at an address. +/// +/// @param address Address of an engine function. +/// @param function Name of a function. +/// @return TRUE if the hook already exists at the address, FALSE otherwise. +func var int IsHook(var int address, var string function) {}; + +/// Alias to IsHook with funcID as parameter. +/// +/// @param address Address of an engine function. +/// @param funcID ID of a function. +/// @return TRUE if the hook already exists at the address, FALSE otherwise. +func var int IsHookI(var int address, var int funcID) {}; + +/// Alias to IsHook with function as parameter. +/// +/// @param address Address of an engine function. +/// @param function Daedalus function. +/// @return TRUE if the hook already exists at the address, FALSE otherwise. +func var int IsHookF(var int address, var func function) {}; + +/// Removes a function from a hook so that it is no longer called. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param function Name of Daedalus function that should no longer be called. +func void RemoveHook(var int address, var int oldInstr, var string function) {}; + +/// Alias to RemoveHook with funcID. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param funcID ID of Daedalus function that should no longer be called. +func void RemoveHookI(var int address, var int oldInstr, var int funcID) {}; + +/// Alias for RemoveHook with func parameter. +/// +/// @param address Address of an engine function to which the function should be attached. +/// @param oldInstr The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +/// @param function Daedalus function that should no longer be called. +func void RemoveHookF(var int address, var int oldInstr, var func function) {}; + +/// Replaces an engine function with a Daedalus function. +/// +/// @param address Address of the engine function to be replaced. +/// @param thiscall_numparams Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). +/// @param replaceFunc Name of a Daedalus function to be called instead. +func void ReplaceEngineFunc(var int address, var int thiscall_numparams, var string replaceFunc) {}; + +/// Alias to ReplaceEngineFunc with funcID. +/// +/// @param address Address of the engine function to be replaced. +/// @param thiscall_numparams Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). +/// @param funcID ID of a Daedalus function to be called instead. +func void ReplaceEngineFuncI(var int address, var int thiscall_numparams, var int funcID) {}; + +/// Alias to ReplaceEngineFunc with func parameter. +/// +/// @param address Address of the engine function to be replaced. +/// @param thiscall_numparams Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). +/// @param function Daedalus function to be called instead. +func void ReplaceEngineFuncF(var int address, var int thiscall_numparams, var func function) {}; + +/// Makes sure that an engine function is simply skipped. This is very delicate and will not always work so easily. +/// +/// @param address Address of the engine function to be skipped. +/// @param thiscall_numparams Number of parameters passed to the engine function, if it is a stdcall or thiscall (otherwise 0). +func void DisableEngineFunc(var int address, var int thiscall_numparams) {}; + +/// Simple function to replace `return FALSE` in hook. +func void Hook_ReturnFalse() {}; + +/// Simple function to replace `return TRUE` in hook. +func void Hook_ReturnTrue() {}; + +// ========================================================= +// +// Int64 +// +// ========================================================= + +/// Writes `lo` and `hi` in one place (dest). Makes Int64, `hi` has to be `-1` for negative 32bit `lo`. +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. +/// @param hi High part of integer. +/// @param lo Low part of integer. +func void mk64(var int dest, var int hi, var int lo) {}; + +/// Negates the integer: `*dest <- -(*dest)` +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. +func void neg64(var int dest) {}; + +/// Adds `src` to `dest`: `*dest <- *dest + *src` +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. +/// @param src A pointer to an Int64 object. Will not change. +func void add64(var int dest, var int src) {}; + +/// Subtracts `src` from `dest`: `*dest <- *dest - *src` +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. +/// @param src A pointer to an Int64 object. Will not change. +func void sub64(var int dest, var int src) {}; + +/// Multiplies `dest` by `src`: `*dest <- (*dest) * (*src)` +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. +/// @param src A pointer to an Int64 object. Will not change. +func void mul64(var int dest, var int src) {}; + +/// Divides `dest` by `src`: `*dest <- *dest / *src` +/// +/// @param dest A pointer to an Int64 object or just 8 bytes of free memory. Will be changed. +/// @param src A pointer to an Int64 object. Will not change. +func void div64(var int dest, var int src) {}; + +// ========================================================= +// +// Interface +// +// ========================================================= + +/// Better alternative for MEM_GetSysTime() from Ikarus. +/// +/// @return The function returns elapsed time since game (system) startup. +func int sysGetTime() {}; + +/// Generates a full zColor. +/// +/// @param r Red channel value (0..255) +/// @param g Green channel value (0..255) +/// @param b Blue channel value (0..255) +/// @param a Alpha (0..255, 0 = invisible) +/// +/// @return The function returns a zColor object. +func int RGBA(var int r, var int g, var int b, var int a) {}; + +/// Overrides the alpha value of a given zColor. +/// +/// @param zCol zColor to modify +/// @param a New alpha value +/// +/// @return The function returns a modified zColor object. +func int ChangeAlpha(var int zCol, var int a) {}; + +/// Returns the alpha value of a given zColor. +/// +/// @param zCol zColor to get alpha from +func int GetAlpha(var int zCol) {}; + +/// Creates a new zCViewText on the screen with PermMem that can be freely edited. +/// +/// @param text The text of the zCViewText +/// @param font Font of text +/// +/// @return The function returns a handle to zCViewText. +func int Print_CreateText(var string text, var string font) {}; + +/// Print_CreateText but returns a pointer to zCViewText instead of a handle. +/// +/// @param text The text of the zCViewText +/// @param font Font of text +/// +/// @return The function returns a pointer to zCViewText. +func int Print_CreateTextPtr(var string text, var string font) {}; + +/// Print_CreateTextPtr but with an additional parameter to choose the color of text. +/// +/// @param text The text of the zCViewText +/// @param font Font of text +/// @param color zColor, e.g., generated with RGBA function +/// +/// @return The function returns a pointer to zCViewText. +func int Print_CreateTextPtrColored(var string text, var string font, var int color) {}; + +/// Returns zCViewText instance from handle. +/// +/// @param hndl Handle to zCViewText +func zCViewText Print_GetText(var int hndl) {}; + +/// Returns zCViewText pointer from handle. +/// +/// @param hndl Handle to zCViewText +func int Print_GetTextPtr(var int hndl) {}; + +/// Removes a zCViewText from the screen. +/// +/// @param hndl Handle to zCViewText (from Print_CreateText or Print_Ext) +func void Print_DeleteText(var int hndl) {}; + +/// Changes the alpha value of a given zCViewText. +/// +/// @param hndl Handle to zCViewText +/// @param a New alpha value +func void Print_SetAlpha(var int hndl, var int a) {}; + +/// Print_SetAlpha but with a pointer to zCViewText instead of a handle. +/// +/// @param ptr Pointer to zCViewText +/// @param a New alpha value +func void PrintPtr_SetAlpha(var int ptr, var int a) {}; + +/// Writes the current resolution to the Print_Screen array and the current aspect ratio to Print_Ratio variable. +func void Print_GetScreenSize() {}; + +/// Converts pixel position to a virtual position. +/// +/// @param pxl Pixel position to convert +/// @param dim PS_X or PS_Y (see Print_Screen) +/// +/// @return The function returns a virtual position of a given pixel position. +func int Print_ToVirtual(var int pxl, var int dim) {}; + +/// Print_ToVirtualF but returns Ikarus float value instead of an integer. +/// +/// @param pxl Pixel position to convert +/// @param dim PS_X or PS_Y (see Print_Screen) +/// +/// @return The function returns a virtual position of a given pixel position as an Ikarus float. +func int Print_ToVirtualF(var int pxl, var int dim) {}; + +/// Converts virtual position to a pixel position. +/// +/// @param vrt Virtual position to convert +/// @param dim PS_X or PS_Y (see Print_Screen) +/// +/// @return The function returns a pixel position of a given virtual position. +func int Print_ToPixel(var int vrt, var int dim) {}; + +/// Print_ToPixelF but returns Ikarus float value instead of an integer. +/// +/// @param vrt Virtual position to convert +/// @param dim PS_X or PS_Y (see Print_Screen) +/// +/// @return The function returns a pixel position of a given virtual position as an Ikarus float. +func int Print_ToPixelF(var int vrt, var int dim) {}; + +/// Gets the size in the specified dimension ratioed by the screen. +/// +/// @param size Size to convert +/// @param dim PS_X or PS_Y (see Print_Screen) +/// +/// @return The function returns size correctly calculated to the ratio. +func int Print_ToRatio(var int size, var int dim) {}; + +/// Converts angle in degrees to radians. +/// +/// @param angle Angle in degrees +/// +/// @return The function returns a calculated angle in radians. +func int Print_ToRadian(var int angle) {}; + +/// Converts angle in radians to degrees. +/// +/// @param angle Angle in radians +/// +/// @return The function returns a calculated angle in degrees. +func int Print_ToDegree(var int angle) {}; + +/// Returns a pointer to a zCFont by its name. +/// +/// @param font Name of font +func int Print_GetFontPtr(var string font) {}; + +/// Returns a name of a zCFont from its pointer. +/// +/// @param fontPtr Pointer to font +func string Print_GetFontName(var int fontPtr) {}; + +/// Returns the width of a string in pixels. +/// +/// @param s Measured string +/// @param font Name of font +/// +/// @return The function returns the width of the string in pixels. +func int Print_GetStringWidth(var string s, var string font) {}; + +/// Print_GetStringWidthPtr but with a zCFont pointer instead of a name. +/// +/// @param s Measured string +/// @param font zCFont pointer +/// +/// @return The function returns the width of the string in pixels. +func int Print_GetStringWidthPtr(var string s, var int font) {}; + +/// Returns the height of a string in pixels. +/// +/// @param font Name of font +/// +/// @return The function returns the height of a string in pixels. +func int Print_GetFontHeight(var string font) {}; + +/// Like the external PrintScreen, writes a text on the screen, but with more options. +/// +/// @param x X coordinate on the screen (virtual) +/// @param y Y coordinate on the screen (virtual) +/// @param text Displayed text +/// @param font Name of font +/// @param color zColor, e.g., generated with RGBA function +/// @param time Display time in milliseconds (-1 = permanent) +/// +/// @return If time == -1, a valid handle is returned. If time != -1, the print is only volatile and no handle is returned. +func int Print_Ext(var int x, var int y, var string text, var string font, var int color, var int time) {}; + +/// Print_ExtPxl but with pixel coordinates instead of virtual. +/// +/// @param x X coordinate on the screen (pixel) +/// @param y Y coordinate on the screen (pixel) +/// @param text Displayed text +/// @param font Name of font +/// @param color zColor, e.g., generated with RGBA function +/// @param time Display time in milliseconds (-1 = permanent) +/// +/// @return If time == -1, a valid handle is returned. If time != -1, the print is only volatile and no handle is returned. +func int Print_ExtPxl(var int x, var int y, var string text, var string font, var int color, var int time) {}; + +/// Returns the longest line from text as a string, using the default line separator tilde ~. +/// +/// @param text Measured text +/// @param font Name of font +/// +/// @return The function returns the longest line from text as a string. +func string Print_LongestLine(var string text, var string font) {}; + +/// Returns the longest line from text as a string, but you specify a new line separator. +/// +/// @param text Measured text +/// @param font Name of font +/// @param separator New line separator +/// +/// @return The function returns the longest line from text as a string. +func string Print_LongestLineExt(var string text, var string font, var string separator) {}; + +/// Returns the longest line width in pixels, using the default line separator tilde ~. +/// +/// @param text Measured text +/// @param font Name of font +/// +/// @return The function returns the longest line width in pixels. +func int Print_LongestLineLength(var string text, var string font) {}; + +/// Returns the longest line width in pixels, but allows you to specify a new line separator. +/// +/// @param text Measured text +/// @param font Name of font +/// @param separator New line separator +/// +/// @return The function returns the longest line width in pixels. +func int Print_LongestLineLengthExt(var string text, var string font, var string separator) {}; + +/// Creates a text field (view with text) using virtual coordinates. +/// +/// @param x X coordinate (virtual) +/// @param y Y coordinate (virtual) +/// @param text Text to be printed +/// @param font Name of font +/// @param height A specific line height +/// +/// @return The function returns a text field pointer. Look at the Print_TextField return value to see an example. +func int Print_TextField(var int x, var int y, var string text, var string font, var int height) {}; + +/// Print_TextFieldPxl but with pixel coordinates. +/// +/// @param x X coordinate (pixel) +/// @param y Y coordinate (pixel) +/// @param text Text to be printed +/// @param font Name of font +/// +/// @return The function returns a text field pointer. Look at the Print_TextField return value to see an example. +func int Print_TextFieldPxl(var int x, var int y, var string text, var string font) {}; + +/// Print_TextFieldColored but you specify the color of the text. +/// +/// @param x X coordinate (virtual) +/// @param y Y coordinate (virtual) +/// @param text Text to be printed +/// @param font Name of font +/// @param height A specific line height +/// @param color zColor, e.g., generated with RGBA function +/// +/// @return The function returns a text field pointer. Look at the Print_TextField return value to see an example. +func int Print_TextFieldColored(var int x, var int y, var string text, var string font, var int height, var int color) {}; + +/// Same function as the external Print, but with smooth animations. The effect can be changed as desired with the user constants. +/// +/// @param txt Printed text +func void PrintS(var string txt) {}; + +/// PrintS but with an additional parameter to choose the color of the text. +/// +/// @param txt Printed text +/// @param color zColor, e.g., generated with RGBA function +func void PrintS_Ext(var string txt, var int color) {}; + +/// Version of PrintS that enqueues in the given NPC's AI queue. +/// +/// @param slf NPC to whose AI queue the function is enqueued +/// @param txt Printed text +func void AI_PrintS(var c_npc slf, var string txt) {}; + +/// Version of PrintS_Ext that enqueues in the given NPC's AI queue. +/// +/// @param slf NPC to whose AI queue the function is enqueued +/// @param txt Printed text +/// @param color zColor, e.g., generated with RGBA function +func void AI_PrintS_Ext(var c_npc slf, var string txt, var int color) {}; + +// ========================================================= +// +// ItemHelper +// +// ========================================================= + +/// Gets an oCItem pointer from a C_ITEM instance. +/// +/// @param instance C_ITEM instance to get the pointer of +/// +/// @return The function returns an oCItem pointer of the C_ITEM instance. +func int ITM_GetPtr(var int instance) {}; + +// ========================================================= +// +// List +// +// ========================================================= + +/// Creates a new list with an initial value. +/// +/// @param data The value of the first list element. +/// +/// @return The function returns a pointer to the created list. +func int List_Create(var int data) {}; + +/// Appends a value to the end of the list. +/// +/// @param list The list to which the value is appended. +/// @param data The value to be appended. +func void List_Add(var int list, var int data) {}; + +/// Adds a value before the first element of the list. +/// +/// @param list The list to which the value is added. +/// @param data The value to be added. +func void List_AddFront(var int list, var int data) {}; + +/// Inserts a value between two list elements. +/// +/// @param list The list in which the value is inserted. +/// @param offset The number of the list element after which the value is inserted. +/// @param data The value to be inserted. +func void List_AddOffset(var int list, var int offset, var int data) {}; + +/// Sets a list element to a specific value. +/// +/// @param node Pointer to the list element. +/// @param data The value to be written into the list element. +func void List_Set(var int node, var int data) {}; + +/// Retrieves the value of a list element. +/// +/// @param list The list from which the element is retrieved. +/// @param nr The number of the list element. +/// +/// @return The function returns the value of the specified list element. +func int List_Get(var int list, var int nr) {}; + +/// Returns a pointer to a list element. +/// +/// @param list The list from which the element is retrieved. +/// @param nr The number of a list element. +/// +/// @return The function returns a pointer to the specified list element. +func int List_Node(var int list, var int nr) {}; + +/// Returns the length of the list (the number of all elements). +/// +/// @param list The list for which the length is calculated. +/// +/// @return The function returns the number of elements in the list. +func int List_Length(var int list) {}; + +/// Checks if the list has the specified length. +/// +/// @param list The list to check. +/// @param length The desired length. +/// +/// @return The function returns a boolean value indicating whether the list has the specified length or not. +func int List_HasLength(var int list, var int length) {}; + +/// Returns the last list element of the list. +/// +/// @param list The list from which the last element is retrieved. +/// +/// @return The function returns a pointer to the last list element. +func int List_End(var int list) {}; + +/// Concatenates two lists. +/// +/// @param list The first list. +/// @param list2 The second list. Its beginning is appended to the end of the first list. +func void List_Concat(var int list, var int list2) {}; + +/// Returns the last list element with a specific value. +/// +/// @param list The list in which to search for the value. +/// @param data The value to search for. +/// +/// @return The function returns the number of the last list element with the value data. +func int List_Contains(var int list, var int data) {}; + +/// Calls a function for each list element, passing a pointer to the list element as a parameter. +/// +/// @param list The list to iterate over. +/// @param function Name of a function to be called for each list element (void handler(var int node)). +func void List_For(var int list, var string function) {}; + +/// Similar to List_For, but with a function parameter instead of a string. +/// +/// @param list The list to iterate over. +/// @param function The function to be called for each list element (void handler(var int node)). +func void ListForF(var int list, var func function) {}; + +/// Similar to List_For, but with a function parameter instead of a string. +/// +/// @param list The list to iterate over. +/// @param funcID ID of a function to be called for each list element (void handler(var int node)). +func void List_ForI(var int list, var int funcID) {}; + +/// Deletes a list element. All subsequent elements shift position. +/// +/// @param list The list from which an element is deleted. +/// @param nr The number of the list element to be deleted. +func void List_Delete(var int list, var int nr) {}; + +/// Destroys the entire list. +/// +/// @param list The list to be destroyed. +func void List_Destroy(var int list) {}; + +/// Returns a pointer to a memory area containing all values of the list. +/// +/// @param list The list to be converted to an array. +/// +/// @return The function returns a memory area containing all the values of the list. +func int List_ToArray(var int list) {}; + +/// Moves the specified list node down by one position in the list. +/// +/// @param list The list in which the node is located. +/// @param node The node to be moved down. +func void List_MoveDown(var int list, var int node) {}; + +/// Moves the specified list node up by one position in the list. +/// +/// @param list The list in which the node is located. +/// @param node The node to be moved up. +func void List_MoveUp(var int list, var int node) {}; + +/// Inserts a value into a sorted list while preserving the sort order. +/// +/// @param list The list to insert the value into. +/// @param data The value to be inserted. +/// @param compare A comparison function used to determine the sort order. +func void List_InsertSorted(var int list, var int data, var func compare) {}; + +/// Creates a new list with an initial value (for zCListSort). +/// +/// @param data The value of the first list element. +/// +/// @return The function returns a pointer to the created list. +func int List_CreateS(var int data) {}; + +/// Appends a value to the end of the list (for zCListSort). +/// +/// @param list The list to which the value is appended. +/// @param data The value to be appended. +func void List_AddS(var int list, var int data) {}; + +/// Adds a value before the first element of the list (for zCListSort). +/// +/// @param list The list to which the value is added. +/// @param data The value to be added. +func void List_AddFrontS(var int list, var int data) {}; + +/// Inserts a value between two list elements (for zCListSort). +/// +/// @param list The list in which the value is inserted. +/// @param offset The number of the list element after which the value is inserted. +/// @param data The value to be inserted. +func void List_AddOffsetS(var int list, var int offset, var int data) {}; + +/// Sets a list element to a specific value (for zCListSort). +/// +/// @param node Pointer to the list element. +/// @param data The value to be written into the list element. +func void List_SetS(var int node, var int data) {}; + +/// Retrieves the value of a list element (for zCListSort). +/// +/// @param list The list from which the element is retrieved. +/// @param nr The number of the list element. +/// +/// @return The function returns the value of the specified list element. +func int List_GetS(var int list, var int nr) {}; + +/// Returns a pointer to a list element (for zCListSort). +/// +/// @param list The list from which the element is retrieved. +/// @param nr The number of a list element. +/// +/// @return The function returns a pointer to the specified list element. +func int List_NodeS(var int list, var int nr) {}; + +/// Returns the length of the list (the number of all elements) (for zCListSort). +/// +/// @param list The list for which the length is calculated. +/// +/// @return The function returns the number of elements in the list. +func int List_LengthS(var int list) {}; + +/// Checks if the list has the specified length (for zCListSort). +/// +/// @param list The list to check. +/// @param length The desired length. +/// +/// @return The function returns a boolean value indicating whether the list has the specified length or not. +func int List_HasLengthS(var int list, var int length) {}; + +/// Returns the last list element of the list (for zCListSort). +/// +/// @param list The list from which the last element is retrieved. +/// +/// @return The function returns a pointer to the last list element. +func int List_EndS(var int list) {}; + +/// Concatenates two lists (for zCListSort). +/// +/// @param list The first list. +/// @param list2 The second list. Its beginning is appended to the end of the first list. +func void List_ConcatS(var int list, var int list2) {}; + +/// Returns the last list element with a specific value (for zCListSort). +/// +/// @param list The list in which to search for the value. +/// @param data The value to search for. +/// +/// @return The function returns the number of the last list element with the value data. +func int List_ContainsS(var int list, var int data) {}; + +/// Calls a function for each list element, passing a pointer to the list element as a parameter (for zCListSort). +/// +/// @param list The list to iterate over. +/// @param function Name of a function to be called for each list element (void handler(var int node)). +func void List_ForS(var int list, var string function) {}; + +/// Similar to List_For, but with a function parameter instead of a string (for zCListSort). +/// +/// @param list The list to iterate over. +/// @param function The function to be called for each list element (void handler(var int node)). +func void ListForFS(var int list, var func function) {}; + +/// Similar to List_For, but with a function parameter instead of a string (for zCListSort). +/// +/// @param list The list to iterate over. +/// @param funcID ID of a function to be called for each list element (void handler(var int node)). +func void List_ForIS(var int list, var int funcID) {}; + +/// Deletes a list element. All subsequent elements shift position (for zCListSort). +/// +/// @param list The list from which an element is deleted. +/// @param nr The number of the list element to be deleted. +func void List_DeleteS(var int list, var int nr) {}; + +/// Destroys the entire list (for zCListSort). +/// +/// @param list The list to be destroyed. +func void List_DestroyS(var int list) {}; + +/// Returns a pointer to a memory area containing all values of the list (for zCListSort). +/// +/// @param list The list to be converted to an array. +/// +/// @return The function returns a memory area containing all the values of the list. +func int List_ToArrayS(var int list) {}; + +/// Moves the specified list node down by one position in the list (for zCListSort). +/// +/// @param list The list in which the node is located. +/// @param node The node to be moved down. +func void List_MoveDownS(var int list, var int node) {}; + +/// Moves the specified list node up by one position in the list (for zCListSort). +/// +/// @param list The list in which the node is located. +/// @param node The node to be moved up. +func void List_MoveUpS(var int list, var int node) {}; + +/// Inserts a value into a sorted list while preserving the sort order (for zCListSort). +/// +/// @param list The list to insert the value into. +/// @param data The value to be inserted. +/// @param compare A comparison function used to determine the sort order. +func void List_InsertSortedS(var int list, var int data, var func compare) {}; + +/// Compares two integer values using a specified comparison function. +/// +/// @param data1 The first integer value. +/// @param data2 The second integer value. +/// @param compare One of the comparison functions to use for the comparison. +/// +/// @return The return value of the specified comparison function. +func int List_Compare(var int data1, var int data2, var func compare) {}; + +/// Compares two integer values in ascending order. +/// +/// @param data1 The first integer value. +/// @param data2 The second integer value. +/// +/// @return The function returns TRUE if data1 is greater than data2, FALSE otherwise. +func int List_CmpAscending(var int data1, var int data2) {}; + +/// Compares two integer values in descending order. +/// +/// @param data1 The first integer value. +/// @param data2 The second integer value. +/// +/// @return The function returns TRUE if data1 is less than data2, FALSE otherwise. +func int List_CmpDescending(var int data1, var int data2) {}; + +/// Compares two unsigned integer values in ascending order. +/// +/// @param data1 The first unsigned integer value. +/// @param data2 The second unsigned integer value. +/// +/// @return The function returns TRUE if data1 is greater than data2, FALSE otherwise. +func int List_CmpAscendingUnsigned(var int data1, var int data2) {}; + +/// Compares two unsigned integer values in descending order. +/// +/// @param data1 The first unsigned integer value. +/// @param data2 The second unsigned integer value. +/// +/// @return The function returns TRUE if data1 is less than data2, FALSE otherwise. +func int List_CmpDescendingUnsigned(var int data1, var int data2) {}; + +// ========================================================= +// +// Locals +// +// ========================================================= + +/// Activates the 'Locals' feature in a function. +/// +/// This function is used to enable the 'Locals' feature in your code. It should be added at the +/// beginning of the function that should receive "real" local variables. +func void locals() {}; + +/// Create a block of code to be executed when a function is exited. +/// +/// The 'Final' function is used to create a block of code that is executed after the function it +/// is defined in is exited, regardless of when or where the function is exited. It can be used to +/// emulate Java's 'final' clause. +/// +/// @return 1 if the 'Final' block is executed, 0 otherwise. +func int Final() {}; + +// ========================================================= +// +// Misc +// +// ========================================================= + +/// Calculates the arcus tangent of an angle between the origin and a point (x, y). +/// +/// @param x The X-coordinate. +/// @param y The Y-coordinate. +/// +/// @return The arcus tangent in radians as an Ikarus float. +func float atan2f(var int x, var int y) {}; + +/// Calculates the sine of an angle given in radians. +/// +/// @param angle The angle in radians as an Ikarus float. +/// +/// @return The sine of the angle. +func float sin(var float angle) {}; + +/// Calculates the cosine of an angle given in radians. +/// +/// @param angle The angle in radians as an Ikarus float. +/// +/// @return The cosine of the angle. +func float cos(var float angle) {}; + +/// Calculates the tangent of an angle given in radians. +/// +/// @param angle The angle in radians as an Ikarus float. +/// +/// @return The tangent of the angle. +func float tan(var float angle) {}; + +/// Calculates the arcus sine. +/// +/// @param sine The sine of an angle as an Ikarus float. +/// +/// @return The arcus sine of the angle. +func float asin(var float sine) {}; + +/// Calculates the arcus cosine. +/// +/// @param cosine The cosine of an angle as an Ikarus float. +/// +/// @return The arcus cosine of the angle. +func float acos(var float cosine) {}; + +/// Calculates the distance between two points on a two-dimensional plane. +/// +/// @param x1 The X-coordinate of the first point. +/// @param x2 The X-coordinate of the second point. +/// @param y1 The Y-coordinate of the first point. +/// @param y2 The Y-coordinate of the second point. +/// +/// @return The distance between the two points. +func int distance2D(var int x1, var int x2, var int y1, var int y2) {}; + +/// Calculates the distance between two points on a two-dimensional plane with Ikarus floats. +/// +/// @param x1 The X-coordinate of the first point. +/// @param x2 The X-coordinate of the second point. +/// @param y1 The Y-coordinate of the first point. +/// @param y2 The Y-coordinate of the second point. +/// +/// @return The distance between the two points as an Ikarus float. +func float distance2Df(var float x1, var float x2, var float y1, var float y2) {}; + +// ========================================================= +// +// PermMem +// +// ========================================================= + +/// Creates a handle to a new instance of `inst`. +/// +/// @param inst A valid instance used as a "constructor". +/// +/// @return A new, valid PermMem handle. +func int new(var int inst) {}; + +/// Similar to `new`, but here a pointer is returned directly and not a handle. Caution! Not managed by PermMem! +/// +/// @param inst A valid instance used as a "constructor". +/// +/// @return A pointer to the new instance. +func int create(var int inst) {}; + +/// "Wraps" a handle "around" a pointer so that the pointer can be used with any function that expects handles. Only conditionally managed by PermMem. +/// +/// @param inst A valid instance determining the type of the handle. +/// @param ptr Pointer to wrap. +/// +/// @return A handle with `ptr` as content. +func int wrap(var int inst, var int ptr) {}; + +/// Cleans the handle. After that, it is invalid. +/// +/// @param hndl Valid PermMem handle. +func void clear(var int hndl) {}; + +/// Frees the handle. The reserved memory is not deleted; the handle becomes invalid. +/// +/// @param hndl Valid PermMem handle. +func void release(var int hndl) {}; + +/// Cleans the handle just like `clear`, but the destructor is also called. +/// +/// @param hndl Valid PermMem handle. +func void delete(var int hndl) {}; + +/// Cleans the handle just like `clear`, but the destructor is also called. +/// +/// @param ptr The pointer to be cleaned. +/// @param inst Instance used in `create` function. +func void free(var int ptr, var int inst) {}; + +/// Returns the instance of the handle. +/// +/// @param hndl Valid PermMem handle. +/// +/// @return The instance of the handle. +func instance get(var int hndl) {}; + +/// Returns a pointer to the instance of the handle. +/// +/// @param hndl Valid PermMem handle. +/// +/// @return A pointer to the instance of the handle. +func int getPtr(var int hndl) {}; + +/// Sets the pointer of a handle. +/// +/// @param hndl Valid PermMem handle. +/// @param ptr New pointer for the handle. +func void setPtr(var int hndl, var int ptr) {}; + +/// Returns the instance used to create the given handle in `new` function. +/// +/// @param hndl Valid PermMem handle. +/// +/// @return The instance used to create the handle in the `new` function. +func int getInst(var int hndl) {}; + +/// Returns the number of handles managed by PermMem. +/// +/// @return The number of handles managed by PermMem. +func int numHandles() {}; + +/// Returns the size of the instance's class in bytes. +/// +/// @param inst Any instance. +/// +/// @return The size of the instance's class in bytes. +func int sizeof(var int inst) {}; + +/// Indicates whether the handle exists and is managed by PermMem. +/// +/// @param hndl PermMem's handle. +/// +/// @return TRUE if the handle is valid (managed by PermMem), FALSE otherwise. +func int Hlp_IsValidHandle(var int hndl) {}; + +/// Executes a function for each handle of an instance. +/// +/// @param inst The function is called for this instance. +/// @param fnc The function is called. The signature is `function(int handle)`. +func void foreachHndl(var int inst, var func fnc) {}; + +/// Checks if PermMem has a handle of this instance. +/// +/// @param inst Instance to be checked. +/// +/// @return TRUE if PermMem has a handle of this instance, FALSE otherwise. +func int hasHndl(var int inst) {}; + +/// Function moved to PermMem from Ikarus. Reads string from the array at the `arrayAddress`. +/// +/// @param arrayAddress Memory address of the array. +/// @param index Array offset (array index). +/// +/// @return String from the array if the address is correct. +func string MEM_ReadStringArray(var int arrayAddress, var int index) {}; + +/// Checks if the specified field already exists in the archive (used with archiver/unarchiver). +/// +/// @param name Name of the field. +/// +/// @return TRUE if the field exists in the archive, FALSE otherwise. +func int PM_Exists(var string name) {}; + +/// Universal function to load integers, floats, class pointers, and int arrays. +/// +/// @param name Name of the loaded field. +/// +/// @return The data existing in the archive at the given field. +func int PM_Load(var string name) {}; + +/// Returns an integer stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The integer value stored in the archive. +func int PM_LoadInt(var string name) {}; + +/// Returns a daedalus float stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The daedalus float stored in the archive. +func int PM_LoadFloat(var string name) {}; + +/// Returns a string stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The string stored in the archive. +func string PM_LoadString(var string name) {}; + +/// Returns a function ID stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The function ID stored in the archive. +func int PM_LoadFuncID(var string name) {}; + +/// Returns a function offset stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The function offset stored in the archive. +func int PM_LoadFuncOffset(var string name) {}; + +/// Returns a function pointer stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The function pointer stored in the archive. +func int PM_LoadFuncPtr(var string name) {}; + +/// Returns a class pointer stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return The class pointer stored in the archive. +func int PM_LoadClassPtr(var string name) {}; + +/// Loads a pointer to the class from the archive to `destPtr`. +/// +/// @param name Name of the loaded field. +/// @param destPtr Destination pointer, the address to where it will deserialize the saved data. +func void PM_LoadClass(var string name, var int destPtr) {}; + +/// Returns a pointer to array stored in the archive. +/// +/// @param name Name of the loaded field. +/// +/// @return A pointer to the array stored in the archive. +func int PM_LoadArray(var string name) {}; + +/// Loads a pointer to array from the archive to `destPtr`. +/// +/// @param name Name of the loaded field. +/// @param destPtr Destination pointer, the address to where it will deserialize the saved data. +func void PM_LoadArrayToPtr(var string name, var int destPtr) {}; + +/// Universal function to load array or class pointer from the archive to `destPtr`. +/// +/// @param name Name of the loaded field. +/// @param destPtr Destination pointer, the address to where it will deserialize the saved data. +func void PM_LoadToPtr(var string name, var int destPtr) {}; + +// ========================================================= +// +// Queue +// +// ========================================================= + +/// Creates a new queue and returns a handle to it. +/// +/// @return A handle to a queue. +func int Q_Create() {}; + +/// Appends an integer to the back of the queue. +/// +/// @param queue Handle of a queue. +/// @param value The value to be appended to the queue. +func void Q_Enqueue(var int queue, var int value) {}; + +/// Checks if the queue is empty. +/// +/// @param queue Handle of a queue. +/// +/// @return TRUE if the queue is empty, FALSE otherwise. +func int Q_IsEmpty(var int queue) {}; + +/// Removes the oldest value from the queue and returns it. +/// +/// @param queue Handle of a queue. +/// +/// @return The oldest value in the queue. +func int Q_Advance(var int queue) {}; + +/// Returns the oldest value in the queue without removing it. +/// +/// @param queue Handle of a queue. +/// +/// @return The oldest value in the queue. +func int Q_Peek(var int queue) {}; + +/// Function with the `funcID` is called with every element of the list as a parameter. The list element is passed to the function as a `zCList` pointer. +/// +/// @param queue Handle of a queue. +/// @param funcID ID of function that is executed for all values in the queue (signature: `void (zCList*)`). +func void Q_For(var int queue, var int funcID) {}; + +/// Like `Q_For`, but with function as a parameter instead of a function ID. +/// +/// @param queue Handle of a queue. +/// @param f This function is executed for all values in the queue (signature: `void (zCList*)`). +func void Q_ForF(var int queue, var func f) {}; + +/// Creates a new callback queue and returns a handle to it. +/// +/// @return A handle to a callback queue. +func int CQ_Create() {}; + +/// Appends a function to the callback queue. +/// +/// @param queue Handle of a callback queue. +/// @param function A function with no return value, expecting no parameter. +func void CQ_EnqueueNoData(var int queue, var func function) {}; + +/// Appends a function together with a value to the callback queue. +/// +/// @param queue Handle of a callback queue. +/// @param function A function with no return value, expecting an integer as a parameter. +/// @param data When calling `function`, this value is passed as a parameter. +func void CQ_EnqueueData(var int queue, var func function, var int data) {}; + +/// 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. +/// +/// @param queue Handle of a callback queue. +/// @param funcID The function ID of a function to be appended to the callback queue. +/// @param data If hasData is not 0, this value is passed to the associated function. +/// @param hasData Must be 0 if the function does not expect an integer as a parameter, otherwise not 0. +func void CQ_Enqueue(var int queue, var int funcID, var int data, var int hasData) {}; + +/// Checks if no function is in the callback queue. +/// +/// @param queue Handle of a callback queue. +/// +/// @return TRUE if the callback queue is empty, FALSE otherwise. +func int CQ_IsEmpty(var int queue) {}; + +/// Executes the foremost function of the callback queue and removes it from the callback queue. +/// +/// @param queue Handle of a callback queue. +func void CQ_Advance(var int queue) {}; + +/// Executes all functions contained in the callback queue. +/// +/// @param queue Handle of a callback queue. +func void CQ_Exhaust(var int queue) {}; + +// ========================================================= +// +// Random +// +// ========================================================= + +/// Returns a random number. +/// +/// @return A random number. +func int r_Next() {}; + +/// Returns a random number from 0 to `max`. +/// +/// @param max Maximum value of the number. +/// +/// @return A random number from 0 to `max`. +func int r_Max(var int max) {}; + +/// Returns a random number from `min` to `max`. +/// +/// @param max Maximum value of the number. +/// @param min Minimum value of the number. +/// +/// @return A random number from `min` to `max`. +func int r_MinMax(var int min, var int max) {}; + +/// Initializes the random number generator. Happens optionally in `LeGo_Init`. +/// +/// @param seed The initializing value. +func void r_Init(var int seed) {}; + +/// Initializes the random number generator based on the current time. +func void r_DefaultInit() {}; + +// ========================================================= +// +// StringBuilder +// +// ========================================================= + +/// Creates and returns a new `StringBuilder`. At the same time, this new `StringBuilder` is set as active. +/// +/// @return A pointer to a new `StringBuilder`. +func int SB_New() {}; + +/// Marks this `StringBuilder` as active. It can now be used with the functions. +/// +/// @param sb Pointer to a `StringBuilder`, returned from `SB_New`. +func void SB_Use(var int sb) {}; + +/// Returns the active `StringBuilder`. +/// +/// @return The active `StringBuilder` object - last set with `SB_Use` or just created with `SB_New`. +func int SB_Get() {}; + +/// If the size of the resulting string is already known, the buffer can be set manually. This is usually not necessary. +/// +/// @param size Size in bytes. Warning! Only works if the `StringBuilder` has been newly created! +func void SB_InitBuffer(var int size) {}; + +/// 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() {}; + +/// Releases the current stream of the `StringBuilder`. The `StringBuilder` is destroyed, and the stream can be obtained via `SB_GetStream`. +func void SB_Release() {}; + +/// Completely destroys the `StringBuilder`. +func void SB_Destroy() {}; + +/// Returns a copy of the stream as a string. +/// +/// @return A copy of the active `StringBuilder` as a string. If the `StringBuilder` object doesn't have a buffer allocated, an empty string is returned. +func string SB_ToString() {}; + +/// Returns a copy of the stream in raw format. +/// +/// @return A copy of the stream in raw format (`char[]`). +func int SB_ToStream() {}; + +/// Doesn't copy the stream but returns it as it is. +/// +/// @return The stream as it is. `SB_Destroy` or `SB_Clear` destroy the returned pointer. +func int SB_GetStream() {}; + +/// Returns the current length of the stream. Similar to `STR_Len` from Ikarus. +/// +/// @return The current length of the active `StringBuilder`. +func int SB_Length() {}; + +/// Sets the length of the stream. When increasing, zero bytes are appended. +/// +/// @param length The new length of the stream. +func void SB_SetLength(var int length) {}; + +/// Appends a string to the active `StringBuilder`. +/// +/// @param s The appended string. +func void SB(var string s) {}; + +/// Appends an integer in text form to the active `StringBuilder`. +/// +/// @param i The appended integer. +func void SBi(var int i) {}; + +/// Appends a byte to the active `StringBuilder`. (e.g., 82 for 'R' - An ASCII table can be quickly found) +/// +/// @param c The appended byte (ASCII table character). +func void SBc(var int c) {}; + +/// Appends a raw bytes array to the active `StringBuilder`. +/// +/// @param ptr Pointer to the appended array. +/// @param len Length of an array. +func void SBraw(var int ptr, var int len) {}; + +/// Appends a Daedalus float in text form to the active `StringBuilder`. +/// +/// @param x The appended Daedalus float value. +func void SBflt(var float x) {}; + +/// Appends an Ikarus float in text form to the active `StringBuilder`. +/// +/// @param x The appended Ikarus float value. +func void SBf(var int x) {}; + +/// Appends a 4-byte raw data (interpreted as an integer `x`) to the active `StringBuilder`. +/// +/// @param x The appended value. +func void SBw(var int x) {}; + +/// Makes escape sequences out of non-writable characters. For example, newline character '\n' becomes '\\n', tab character '\t' becomes '\\t', etc. +/// +/// @param s0 The string to be added escape sequences. +/// +/// @return A new string with escape sequences added for special characters. +func string STR_Escape(var string s0) {}; + +/// Counterpart to `STR_Escape`. Escape sequences like '\n', '\r' or '\t' are converted back. +/// +/// @param s0 The string to be removed escape sequences. +/// +/// @return A new string with escape sequences replaced by their corresponding characters. +func string STR_Unescape(var string s0) {}; + +/// Checks if the input string `str` starts with the specified prefix string. +/// +/// @param str The string to be checked. +/// @param start The searched prefix. +/// +/// @return `TRUE` if the string starts with the prefix, `FALSE` is returned otherwise. +func int STR_StartsWith(var string str, var string start) {}; + +/// Creates an array of all string symbols found in the parser's string table. +/// +/// @return The created array. +func int BuildStringSymbolsArray() {}; + +/// Retrieves the symbol at the specified address from the string table. +/// +/// @param address The address of the symbol. +/// +/// @return A parser symbol at the given address. +func int GetStringSymbolByAddr(var int address) {}; + +// ========================================================= +// +// Talents +// +// ========================================================= + +/// Returns a unique ID specific for the provided NPC. +/// +/// @param slf NPC to get ID. +/// +/// @return The function returns the NPC's unique ID. +func int Npc_GetID(var C_NPC slf) {}; + +/// Finds the NPC pointer of an NPC with the given ID. +/// +/// @param ID NPC ID. +/// +/// @return The function returns the NPC pointer. +func int Npc_FindByID(var int ID) {}; + +/// Creates a talent into which you can later save a value for every NPC (just like `AI_Var`). +/// +/// @return A value that can be later used as a talent ID. +func int TAL_CreateTalent() {}; + +/// Sets a new value to the specified talent. +/// +/// @param npc Set the talent value for this NPC. +/// @param talent Talent ID. +/// @param value Value to be set. +func void TAL_SetValue(var C_NPC npc, var int talent, var int value) {}; + +/// Returns the value of a saved talent for the specified NPC. +/// +/// @param npc Get the talent value from this NPC. +/// @param talent Talent ID. +/// +/// @return The function returns the value of the saved talent for the specified NPC. +func int TAL_GetValue(var C_NPC npc, var int talent) {}; + +// ========================================================= +// +// Timer +// +// ========================================================= + +/// Returns the current playing time. If a new game is started, the time is 0. It is measured in milliseconds. +/// +/// @return The function returns current playing time in milliseconds. +func int Timer() {}; + +/// Returns the current game time, but the timer is paused when the game is paused (in the menu or status screen). +/// +/// @return The function returns current playing time in milliseconds, but without measuring time when the game is paused. +func int TimerGT() {}; + +/// Alias to the `Timer` function that returns the time as an Ikarus float value. +/// +/// @return The function returns current playing time as an Ikarus float value. +func int TimerF() {}; + +/// Pauses the timer (and thus all FrameFunctions and running animations). +/// +/// @param on Pause on/off. +func void Timer_SetPause(var int on) {}; + +/// The timer can automatically pause when the game is paused (status screen, main menu...). +/// +/// @param on Automatic pause on/off. +func void Timer_SetPauseInMenu(var int on) {}; + +/// This can be used to query whether the timer is paused. +/// +/// @return The function returns TRUE if the timer is paused, FALSE is returned otherwise. +func int Timer_IsPaused() {}; diff --git a/docs/zengin/scripts/extenders/lego/tools/ai_function.md b/docs/zengin/scripts/extenders/lego/tools/ai_function.md index 5a4e3c8940..c6695dc612 100644 --- a/docs/zengin/scripts/extenders/lego/tools/ai_function.md +++ b/docs/zengin/scripts/extenders/lego/tools/ai_function.md @@ -1,8 +1,9 @@ --- title: AI_Function +description: LeGo package for enqueuing functions to NPC's AI queue --- -# AI Function -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 e.g. cutscenes. +# AI_Function +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. ## Dependencies @@ -39,13 +40,13 @@ func void AI_Function_SS (var C_NPC slf, var func function, var string param1, v func void AI_Function_IS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Int, String func void AI_Function_SI (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Int func void AI_Function_NS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Instance, String -func void AI_Function_SN (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Istance +func void AI_Function_SN (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Instance func void AI_Function_IN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Instance func void AI_Function_NI (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Int ``` Functions with more than two parameters cannot be called, but parameters can be passed indirectly via global variables. -In the called function, `slf` can be accessed as follows: +In the called function, `self` can be accessed as follows: ```dae var oCNpc slf; slf = _^(ECX); ``` diff --git a/docs/zengin/scripts/extenders/lego/tools/ai_function.pl.md b/docs/zengin/scripts/extenders/lego/tools/ai_function.pl.md new file mode 100644 index 0000000000..0357b2d870 --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/ai_function.pl.md @@ -0,0 +1,70 @@ +--- +title: AI_Function +description: Pakiet LeGo do kolejkowania funkcji w kolejce AI dowolnego NPC +--- +# AI_Function - Funkcje AI +Ten pakiet umożliwia wywoływanie funkcji opóźnionych w czasie poprzez kolejkowanie ich w kolejce AI danego NPC. Może to być bardzo przydatne przy pisaniu przerywników filmowych na silniku lub implementacji nowych rutyn. + +## Zależności + +- [HookEngine](hook_engine.md) + +## Inicjalizacja +Zainicjuj za pomocą flagi `LeGo_AI_Function`. +```dae +LeGo_Init(LeGo_AI_Function); +``` +## Implementacja +[:material-github: AI_Function.d na GitHubie](https://github.com/Lehona/LeGo/blob/dev/AI_Function.d) + +## Funkcje +Funkcja `function` jest wywoływana z opóźnieniem: dołącza do kolejki AI `slf`. +```dae +func void AI_Function(var C_NPC slf, var func function) +``` +**Parametry** + +- `#!dae var C_NPC slf` + NPC, do którego kolejki AI dołącza funkcja +- `#!dae var func function` + Funkcja wywoływana z opóźnieniem + +Dodatkowo istnieją pewne przeciążenia `AI_Function`, które pozwalają na wywoływanie funkcji z parametrami. +```dae +func void AI_Function_I (var C_NPC slf, var func function, var int param) {}; // Int +func void AI_Function_N (var C_NPC slf, var func function, var int param) {}; // Instance (e.g. NPC) +func void AI_Function_S (var C_NPC slf, var func function, var string param) {}; // String +func void AI_Function_II (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Int +func void AI_Function_NN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Instance +func void AI_Function_SS (var C_NPC slf, var func function, var string param1, var string param2) {}; // String, String +func void AI_Function_IS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Int, String +func void AI_Function_SI (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Int +func void AI_Function_NS (var C_NPC slf, var func function, var int param1, var string param2) {}; // Instance, String +func void AI_Function_SN (var C_NPC slf, var func function, var string param1, var int param2) {}; // String, Instance +func void AI_Function_IN (var C_NPC slf, var func function, var int param1, var int param2) {}; // Int, Instance +func void AI_Function_NI (var C_NPC slf, var func function, var int param1, var int param2) {}; // Instance, Int +``` +Nie można wywoływać funkcji z więcej niż dwoma parametrami, ale parametry można przekazywać pośrednio przez zmienne globalne. + +W wywołanej funkcji dostęp do `self` można uzyskać w następujący sposób: +```dae +var oCNpc slf; slf = _^(ECX); +``` +!!! Info + Od LeGo 2.7.2 globalna instancja `self` jest dostarczana poprawnie i może być używana bezpośrednio. + +## Przykłady + +### Kolejkowanie prostej funkcji +Zanim funkcja zostanie wywołana, każdy NPC powinien najpierw zakończyć swoją kolejkę AI. + +Tutaj bohater ma biec do Waypointu i dopiero po dotarciu na miejsce ma rozpocząć się ruch kamery. +```dae +func void Example1() { + Npc_ClearAIQueue(hero); + AI_GotoWP(hero, "MYWAYPOINT"); + + AI_Function_S(hero, Wld_SendTrigger, "CAMERASTART"); +}; +``` +Gdy tylko bohater dotrze do Waypointu, wywoływane jest `Wld_SendTrigger("CAMERASTART");`. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/binary_machines.md b/docs/zengin/scripts/extenders/lego/tools/binary_machines.md index e438c1332d..640d14f1b7 100644 --- a/docs/zengin/scripts/extenders/lego/tools/binary_machines.md +++ b/docs/zengin/scripts/extenders/lego/tools/binary_machines.md @@ -1,3 +1,7 @@ +--- +title: BinaryMachines +description: LeGo package for creating, writing and reading your own files +--- # BinaryMachines This package allows you to create and write your own files anywhere in the file system. @@ -22,6 +26,10 @@ func int BW_NewFile(var string file) - `#!dae 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. + ### `BW_Close` Closes the current write stream. ```dae @@ -48,7 +56,7 @@ func void BW_Int(var int data) **Parameters** - `#!dae var int data` - Int value to wirte + Integer value to write ### `BW_Char` Writes the first character from the `data` to the stream. Same as `BW(Str_GetCharAt(data, 0), 1)`. @@ -120,6 +128,11 @@ func int BR_OpenFile(var string file) - `#!dae 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. + + ### `BR_Close` Closes the current read stream. ```dae @@ -156,7 +169,7 @@ func string BR_Char() ``` **Return value** -The function returns the read character. +The function returns the read character as a `string`. ### `BR_String` Reads a string terminated by `\0` from the stream. @@ -213,6 +226,89 @@ func string BR_Text(var int length) The function returns the read string. +### `BR_NextLine` +Changes the read position to the next paragraph, created with [`BW_NextLine`](#bw_nextline) +```dae +func void BR_NextLine() +``` + +## Enginecalls + +### `WIN_GetLastError` +Call of a Win32 API [`GetLastError` function](https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) +```dae +func int WIN_GetLastError() +``` +**Return value** + +The function returns calling thread's last-error code. + +### `WIN_CreateFile` +Call of a Win32 API [`CreateFileA` function](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea) +```dae +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) +``` +**Parameters** + +Full description of parameters can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#parameters) + +**Return value** + +Information about return value can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#return-value) + +### `WIN_WriteFile` +Call of a Win32 API [`WriteFile` function](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile) +```dae +func void WIN_WriteFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToWrite,var int lpNumberOfBytesWritten,var int lpOverlapped) +``` +**Parameters** + +Full description of parameters can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile#parameters) + +### `WIN_ReadFile` +Call of a Win32 API [`ReadFile` function](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile) +```dae +func void WIN_ReadFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToRead,var int lpNumberOfBytesRead,var int lpOverlapped) +``` +**Parameters** + +Full description of parameters can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile#parameters) + +### `WIN_CloseHandle` +Call of a Win32 API [`CloseHandle` function](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle) +```dae +func void WIN_CloseHandle(var int hObject) +``` +**Parameters** + +Full description of parameters can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle#parameters) + +### `WIN_GetFileSize` +Call of a Win32 API [`GetFileSize` function](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize) +```dae +func int WIN_GetFileSize(var int hFile,var int lpFileSizeHigh) +``` +**Parameters** + +Full description of parameters can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize#parameters) + +**Return value** + +Information about return value can be found [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize#return-value) + +### Constants +In addition there are some constants defined for use with the specific engine calls. +```dae +const int CREATE_ALWAYS = 2; +const int OPEN_EXISTING = 3; +const int GENERIC_ALL = 1073741824; +const int GENERIC_READ = -2147483648; +const int FILE_SHARE_READ = 1; +const int FILE_SHARE_WRITE = 2; +const int FILE_SHARE_DELETE = 4; +const int FILE_ATTRIBUTE_NORMAL = 128; +``` + ## Examples ### Save and load variables diff --git a/docs/zengin/scripts/extenders/lego/tools/binary_machines.pl.md b/docs/zengin/scripts/extenders/lego/tools/binary_machines.pl.md new file mode 100644 index 0000000000..5f0c91ad7a --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/binary_machines.pl.md @@ -0,0 +1,410 @@ +--- +title: BinaryMachines +description: Pakiet LeGo do tworzenia, zapisywania i odczytywania własnych plików +--- +# BinaryMachines +Ten pakiet pozwala tworzyć i zapisywać własne pliki w dowolnym miejscu w systemie plików. + +## Zależności +Brak + +## Inicjalizacja +Brak + +## Implementacja +[:material-github: BinaryMachines.d na GitHub](https://github.com/Lehona/LeGo/blob/dev/BinaryMachines.d) + +## BinaryWriter + +### `BW_NewFile` +Tworzy plik o nazwie `file` i otwiera strumień. Nie działa, jeśli strumień jest już otwarty. +```dae +func int BW_NewFile(var string file) +``` +**Parametry** + +- `#!dae var string file` + Nazwa tworzonego pliku + +**Zwracana wartość** + +Funkcja zwraca `TRUE` jeśli plik został pomyślnie utworzony i zainicjalizowany, w przeciwnym razie zwracane jest `FALSE`. + +### `BW_Close` +Zamyka aktualny strumień zapisu. +```dae +func void BW_Close() +``` + +### `BW` +Zapisuje `length` bajtów z `data` do strumienia, maksymalnie 4 bajty. +```dae +func void BW(var int data, var int length) +``` +**Parametry** + +- `#!dae var int data` + Wartość bajtów +- `#!dae var int length` + Liczba bajtów + +### `BW_Int` +Zapisuje 4 bajty z `data` do strumienia. To samo co `BW(data, 4)`. +```dae +func void BW_Int(var int data) +``` +**Parametry** + +- `#!dae var int data` + Wartość całkowita do zapisania + +### `BW_Char` +Zapisuje pierwszy znak z `data` do strumienia. To samo co `BW(Str_GetCharAt(data, 0), 1)`. +```dae +func void BW_Char(var string data) +``` +**Parametry** + +- `#!dae var string data` + Znak do zapisania + +### `BW_String` +Zapisuje `data` zakończone znakiem `\0` do strumienia. +```dae +func void BW_String(var string data) +``` +**Parametry** + +- `#!dae var string data` + Ciąg znaków do zapisania + +### `BW_Byte` +Zapisuje bajt z `data` do strumienia. To samo co `BW(data, 1)`. +```dae +func void BW_Byte(var int data) +``` +**Parametry** + +- `#!dae var int data` + Wartość bajtowa do zapisania + +### `BW_Bytes` +Zapisuje `length` bajtów ze wskaźnika `dataPtr` do strumienia. +```dae +func void BW_Bytes(var int dataPtr, var int length) +``` +**Parametry** + +- `#!dae var int dataPtr` + Wskaźnik danych do zapisania +- `#!dae var int length` + Liczba bajtów + +### `BW_Text` +Zapisuje ciąg znaków do strumienia bez jego zakończenia. Nie można go już odczytać. +```dae +func void BW_Text(var string data) +``` +**Parametry** + +- `#!dae var string data` + Tekst do zapisania + +### `BW_NextLine` +Zapisuje akapit do strumienia. +```dae +func void BW_NextLine() +``` + +## BinaryReader + +### `BR_OpenFile` +Otwiera plik o nazwie `file` i otwiera strumień. Nie działa, jeśli strumień jest już otwarty. +```dae +func int BR_OpenFile(var string file) +``` +**Parametry** + +- `#!dae var string file` + Plik, który ma być otwarty + +**Zwracana wartość** + +Funkcja zwraca `TRUE` jeśli plik został pomyślnie otworzony i zainicjalizowany, w przeciwnym razie zwracane jest `FALSE`. + + +### `BR_Close` +Zamyka aktualny strumień odczytu. +```dae +func void BR_Close() +``` + +### `BR` +Odczytuje bajty ze strumienia. +```dae +func int BR(var int length) +``` +**Parametry** + +- `#!dae var int length` + Liczba bajtów do odczytania (maksymalnie 4) + +**Zwracana wartość** + +Funkcja zwraca odczytaną wartość bajtów. + +### `BR_Int` +Odczytuje 4 bajty ze strumienia. To samo co `BR(4)`. +```dae +func int BR_Int() +``` +**Zwracana wartość** + +Funkcja zwraca odczytaną liczbę całkowitą. + +### `BR_Char` +Odczytuje znak ze strumienia. To samo co `BR(1)`. +```dae +func string BR_Char() +``` +**Zwracana wartość** + +Funkcja zwraca odczytany znak jako `string`. + +### `BR_String` +Odczytuje ciąg znaków zakończony znakiem `\0` ze strumienia. +```dae +func string BR_String() +``` +**Zwracana wartość** + +Funkcja zwraca odczytany ciąg znaków. + +### `BR_Byte` +Odczytuje bajt ze strumienia. +```dae +func int BR_Byte() +``` +**Zwracana wartość** + +Funkcja zwraca odczytany bajt. + +### `BR_Bytes` +Odczytuje bajty ze strumienia. +```dae +func int BR_Bytes(var int length) +``` +**Parametry** + +- `#!dae var int length` + Liczba bajtów do odczytania + +**Zwracana wartość** + +Funkcja zwraca wskaźnik do odczytanych bajtów. + +### `BR_TextLine` +Odczytuje linię ze strumienia. +```dae +func string BR_TextLine() +``` +**Zwracana wartość** + +Funkcja zwraca odczytaną linię. + +### `BR_Text` +Odczytuje ciąg znaków o podanej długości ze strumienia. +```dae +func string BR_Text(var int length) +``` +**Parametry** + +- `#!dae var int length` + Liczba znaków do odczytania + +**Zwracana wartość** + +Funkcja zwraca odczytany ciąg znaków. + +### `BR_NextLine` +Zmienia pozycję odczytu na następny akapit, utworzony za pomocą [`BW_NextLine`](#bw_nextline). +```dae +func void BR_NextLine() +``` + +## Wywołania funkcji silnika + +### `WIN_GetLastError` +Wywołanie [funkcji `GetLastError`](https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) z Win32 API. +```dae +func int WIN_GetLastError() +``` +**Zwracana wartość** + +Funkcja zwraca kod ostatniego błędu wątku wywołującego. + +### `WIN_CreateFile` +Wywołanie [funkcji `CreateFileA`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea) z Win32 API. +```dae +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) +``` +**Parametry** + +Pełny opis parametrów można znaleźć [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#parameters) + +**Zwracana wartość** + +Informacje o zwracanej wartości znajdziesz [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#return-value) + +### `WIN_WriteFile` +Wywołanie [funkcji `WriteFile`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile) z Win32 API. +```dae +func void WIN_WriteFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToWrite,var int lpNumberOfBytesWritten,var int lpOverlapped) +``` +**Parametry** + +Pełny opis parametrów można znaleźć [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile#parameters) + +### `WIN_ReadFile` +Wywołanie [funkcji `ReadFile`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile) z Win32 API. +```dae +func void WIN_ReadFile(var int hFile,var int lpBuffer,var int nNumberOfBytesToRead,var int lpNumberOfBytesRead,var int lpOverlapped) +``` +**Parametry** + +Pełny opis parametrów można znaleźć [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile#parameters) + +### `WIN_CloseHandle` +Wywołanie [funkcji `CloseHandle`](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle) z Win32 API. +```dae +func void WIN_CloseHandle(var int hObject) +``` +**Parametry** + +Pełny opis parametrów można znaleźć [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle#parameters) + +### `WIN_GetFileSize` +Wywołanie [funkcji `GetFileSize`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize) z Win32 API. +```dae +func int WIN_GetFileSize(var int hFile,var int lpFileSizeHigh) +``` +**Parametry** + +Pełny opis parametrów można znaleźć [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize#parameters) + +**Zwracana wartość** + +Informacje o zwracanej wartości znajdziesz [tutaj](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize#return-value) + +### Constants +Dodatkowo istnieją pewne stałe zdefiniowane do użycia z określonymi wywołaniami funkcji silnika. +```dae +const int CREATE_ALWAYS = 2; +const int OPEN_EXISTING = 3; +const int GENERIC_ALL = 1073741824; +const int GENERIC_READ = -2147483648; +const int FILE_SHARE_READ = 1; +const int FILE_SHARE_WRITE = 2; +const int FILE_SHARE_DELETE = 4; +const int FILE_ATTRIBUTE_NORMAL = 128; +``` + +## Przykłady + +### Zapisywanie i wczytywanie zmiennych +```dae +const string filename = "System\MySave.sav"; + +var string s0; // ciąg znaków +var int i1; // liczba całkowita +var int b2; // bajt +var string c3; // znak + +func void SaveMyData() + + +{ + if(BW_NewFile(filename)) // Utwórz nowy plik: + { + BW_String(s0); + BW_Int(i1); + BW_Byte(b2); + BW_Char(c3); // Zapisz dane... + BW_Close(); // ...i zamknij. + }; +}; + +func void LoadMyData() { + if(BR_OpenFile(filename)) // Spróbuj otworzyć plik: + { + s0 = BR_String(); + i1 = BR_Int(); + b2 = BR_Byte(); + c3 = BR_Char(); // Odczytaj wartości... + BR_Close(); // ...i zamknij. + } + else + { + SaveMyData(); // W przeciwnym razie utwórz plik z zapisem. + }; +}; +``` + +### Gratulacje dla gracza +```dae +func void Certificate(var string Username, var int Score) +{ + var string filename; filename = ConcatStrings(Username, "'s Certificate.txt"); + BW_NewFile(filename); // Nazwa użytkownika + "s Certificate.txt". Plik jest w katalogu Gothic. + BW_Text("Gratulacje "); BW_Text(Username); + BW_TextLine("!"); + + BW_Text("Zdobyłeś "); + BW_Text(IntToString(Score)); // Nie BW_Int! + BW_TextLine(" punktów w tej grze."); + + BW_NextLine(); + + BW_Text("Z wyrazami szacunku, Autor"); + BW_Close(); + + /* + Przy wywołaniu: Certificate("Player", 1000); + zostanie utworzony plik o nazwie 'Player's Certificate.txt', który zawierać będzie: + + Gratulacje NazwaGracza! + Zdobyłeś 1000 punktów w tej grze. + + Z wyrazami szacunku, Autor + */ +}; +``` + +### Położenie postaci NPC +```dae +func void BW_NpcPosition(var C_NPC slf) +{ + var int ptr; ptr = MEM_Alloc(60); // 16 * 4 + MEM_CopyBytes(MEM_InstToPtr(slf) + 60, ptr, 60); // Skopiuj slf.trafoObjToWorld + BW_Bytes(ptr, 60); // Zapisz skopiowane 60 bajtów + MEM_Free(ptr); // I posprzątaj... +}; + +func void BR_NpcPosition(var C_NPC slf) +{ + var int ptr; ptr = BR_Bytes(60); // Odczytaj 60 bajtów + MEM_CopyBytes(ptr, MEM_InstToPtr(slf) + 60, 60); // Wklej z powrotem do slf + MEM_Free(ptr); // I posprzątaj ponownie... +}; + +/* + Użycie standardowe: + BW_NewFile(file); + BW_NpcPosition(hero); + BW_Close(); +*/ +``` + +!!! Uwaga + Przykłady zostały pierwotnie napisane przez Gottfrieda i [opublikowane](https://forum.worldofplayers.de/forum/threads/969446-Skriptpaket-Ikarus-3/page3?p=16198713#post16198713) na forum World of Gothic. +` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/event_handler.md b/docs/zengin/scripts/extenders/lego/tools/event_handler.md index 00e60506ef..ac6c7c6d9a 100644 --- a/docs/zengin/scripts/extenders/lego/tools/event_handler.md +++ b/docs/zengin/scripts/extenders/lego/tools/event_handler.md @@ -1,3 +1,7 @@ +--- +title: EventHandler +description: LeGo package for creating new script events and triggering them +--- # EventHandler This package allows to create new events and trigger them at desired times. The [Gamestate](../applications/gamestate.md) package already uses it. @@ -6,7 +10,7 @@ This package allows to create new events and trigger them at desired times. The ## Dependencies -- PermMem +- [PermMem](permmem.md) ## Initialization Initialize with `LeGo_EventHandler` flag. diff --git a/docs/zengin/scripts/extenders/lego/tools/frame_functions.md b/docs/zengin/scripts/extenders/lego/tools/frame_functions.md index 57e633c34e..90fff3d137 100644 --- a/docs/zengin/scripts/extenders/lego/tools/frame_functions.md +++ b/docs/zengin/scripts/extenders/lego/tools/frame_functions.md @@ -1,10 +1,14 @@ +--- +title: FrameFunctions +description: LeGo package for calling script functions on every frame, or every time delay +--- # FrameFunctions The FrameFunctions package allows to call any number of functions called on every frame, or every specified time delay. ## Dependencies -- Floats -- PermMem +- [Floats](../../ikarus/floats.md) +- [PermMem](permmem.md) - [HookEngine](../tools/hook_engine.md) - [Timer](timer.md) @@ -19,55 +23,68 @@ LeGo_Init(LeGo_FrameFunctions); ## Functions ### `FF_Apply` -Adds the Daedalus function `function` to the frame functions list. `function` is called each frame. +Adds the Daedalus function `function` to the running FrameFunctions list. `function` is called each frame. ```dae func void FF_Apply(var func function) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the function ### `FF_ApplyGT` -Adds the Daedalus function `function` to the frame function list. `function` is called every frame except when the game is paused. +Adds the Daedalus function `function` to the running FrameFunctions list. `function` is called every frame except when the game is paused. ```dae func void FF_ApplyGT(var func function) ``` **Parameters** +- `#!dae var func function` + Name of the function + +### `FF_ApplyData` +Adds the Daedalus function `function` to the running FrameFunctions list. The integer parameter `data` is passed to the function `function`. +```dae +func void FF_ApplyData(var func function, var int data) +``` +**Parameters** + - `#!dae var func function` Name of the function. +- `#!dae var int data` + Value passed to the function as a parameter + ### `FF_ApplyExt` -Adds the Daedalus function `function` to the frame function list. The function `function` is called every `delay` milliseconds, and it runs only `cycles` number of times. +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. ```dae func void FF_ApplyExt(var func function, var int delay, var int cycles) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the function - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) ### `FF_ApplyExtGT` -Adds the Daedalus function `function` to the frame function 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. +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. ```dae func void FF_ApplyExtGT(var func function, var int delay, var int cycles) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the function - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) ### `FF_ApplyExtData` -Adds the Daedalus function `function` to the frame function 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`. +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`. ```dae func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data) ``` @@ -76,14 +93,14 @@ func void FF_ApplyExtData(var func function, var int delay, var int cycles, var - `#!dae var func function` Name of the function. - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) - `#!dae var int data` - Value passed to the function as a parameter. + Value passed to the function as a parameter ### `FF_ApplyExtDataGT` -Adds the Daedalus function `function` to the frame function 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. +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. ```dae func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data) ``` @@ -92,11 +109,11 @@ func void FF_ApplyExtData(var func function, var int delay, var int cycles, var - `#!dae var func function` Name of the function. - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) - `#!dae var int data` - Value passed to the function as a parameter. + Value passed to the function as a parameter ### `FF_ApplyOnce` Alias to [FF_Apply](#ff_apply), which only adds the function once, even after multiple calls. @@ -106,7 +123,7 @@ func void FF_ApplyOnce(var func function) **Parameters** - `#!dae var func function` - Name of the function. + Name of the function ### `FF_ApplyOnceGT` Alias to [FF_ApplyGT](#ff_applygt), which only adds the function once, even after multiple calls. Loop doesn't run if the game is paused. @@ -118,19 +135,31 @@ func voidoften FF_ApplyOnceGT(var func function) - `#!dae var func function` Name of the function. +### `FF_ApplyOnceData` +Alias to [FF_ApplyData](#ff_applydata), which only adds the function with the specified parameter once, even after multiple calls. +```dae +func void FF_ApplyOnceData(var func function, var int data) +``` +**Parameters** + +- `#!dae var func function` + Name of the function. +- `#!dae var int data` + Value passed to the function as a parameter + ### `FF_ApplyOnceExt` -Alias to [FF-ApplyExt](#ff_applyext), which adds the function only once after repeated calls. +Alias to [FF_ApplyExt](#ff_applyext), which adds the function only once, after repeated calls. ```dae func void FF_ApplyOnceExt(var func function, var int delay, var int cycles) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the function - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) ### `FF_ApplyOnceExtGT` Alias to [FF_ApplyExtGT](#ff_applyextgt), which adds the function only once after repeated calls. Loop doesn't run if the game is paused. @@ -140,46 +169,87 @@ func void FF_ApplyOnceExtGT(var func function, var int delay, var int cycles) **Parameters** - `#!dae var func function` - Name of the function. + Name of the function - `#!dae var int delay` - Delay between calls in milliseconds. (0 = every frame) + Delay between calls in milliseconds (0 = every frame) - `#!dae var int cycles` - How many times should the function be called. (-1 = endless) + How many times should the function be called (-1 = endless) + +### `FF_ApplyOnceExtData` +Alias to [FF_ApplyExtData](#ff_applyextdata), which adds the function with the specified parameter only once, after repeated calls. +```dae +func void FF_ApplyOnceExtData(var func function, var int delay, var int cycles, var int data) +``` +**Parameters** + +- `#!dae var func function` + Name of the function +- `#!dae var int delay` + Delay between calls in milliseconds (0 = every frame) +- `#!dae var int cycles` + How many times should the function be called (-1 = endless) +- `#!dae var int data` + Value passed to the function as a parameter ### `FF_Active` -Checks whether the function `function` is active. +Checks whether the `function` is active. ```dae func int FF_Active(var func function) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the function + +**Return value** +The function returns `TRUE` if the function is active, `FALSE` if it is not. + +### `FF_ActiveData` +Checks whether the `function` with the specified `data` is active. +```dae +func int FF_ActiveData(var func function, var int data) +``` +**Parameters** + +- `#!dae var func function` + Name of the function +- `#!dae 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. ### `FF_Remove` -Removes specified Daedalus function from the list. +Stops a specific FrameFunction. ```dae func void FF_Remove(var func function) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the stopped function + +### `FF_RemoveAll` +Stops all intsnces of a specific FrameFunction. +```dae +func void FF_RemoveAll(var func function) +``` +**Parameters** + +- `#!dae var func function` + Name of the stopped function ### `FF_RemoveData` -Removes specified Daedalus function with the specified value from the list (see [`FF_ApplyExtData`](#ff_applyextdata) ). +Stops a specific FrameFunction, with the specified value (see [`FF_ApplyExtData`](#ff_applyextdata) ). ```dae func void FF_RemoveData(var func function, var int data) ``` **Parameters** - `#!dae var func function` - Name of the function. + Name of the stopped function - `#!dae var int data` - Value previously passed to the function as a parameter. + Value previously passed to the function as a parameter ## Examples diff --git a/docs/zengin/scripts/extenders/lego/tools/hashtables.md b/docs/zengin/scripts/extenders/lego/tools/hashtables.md index d07f4c4c3e..f0003acd9f 100644 --- a/docs/zengin/scripts/extenders/lego/tools/hashtables.md +++ b/docs/zengin/scripts/extenders/lego/tools/hashtables.md @@ -1,10 +1,14 @@ +--- +title: Hashtables +description: LeGo package implementing Hashtable data structure to gothic scripts +--- # Hashtables Hashtables package is an implementation of hashtables in Gothic. Currently (version 2.8.0) only integers are supported as keys. The Hashtables grow automatically. ## Dependencies -- PermMem +- [PermMem](permmem.md) ## Initialization Initialize with `LeGo_PermMem` flag. @@ -173,3 +177,59 @@ func void HT_Destroy(var int handle) - `#!dae var int handle` The handle of the hashtable to be deleted + +## Examples + +### Simple operations +```dae +func void PrintKeyValuePair(var int key, var int val) +{ + Print(ConcatStrings(ConcatStrings("Key: ", IntToString(key)), ConcatStrings(", Value: ", IntToString(val)))); +}; + +func void example() +{ + // Create a new hashtable + var int hashtableHandle; hashtableHandle = HT_Create(); + + // Insert values into the hashtable + HT_Insert(hashtableHandle, 42, 1); + HT_Insert(hashtableHandle, 23, 2); + HT_Insert(hashtableHandle, 56, 3); + + // Get a value from the hashtable + var int value; value = HT_Get(hashtableHandle, 2); + Print(ConcatStrings("Value associated with key 2: ", IntToString(value))); + + // Check if a key exists in the hashtable + if (HT_Has(hashtableHandle, 3)) + { + Print("Key 3 exists in the hashtable."); + } + else + { + Print("Key 3 does not exist in the hashtable."); + }; + + // Remove a key from the hashtable + HT_Remove(hashtableHandle, 1); + + // Change the value associated with a key + HT_Change(hashtableHandle, 99, 3); + + // Insert a value or change it if the key exists + HT_InsertOrChange(hashtableHandle, 123, 4); + + // Get the number of entries in the hashtable + var int numEntries; numEntries = HT_GetNumber(hashtableHandle); + Print(ConcatStrings("Number of entries in the hashtable: ", IntToString(numEntries))); + + + // Iterate through the hashtable and print key-value pairs + // Function from top of the example is used here + HT_ForEach(hashtableHandle, PrintKeyValuePair); + + // Destroy the hashtable + HT_Destroy(hashtableHandle); +}; +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/hook_dae.md b/docs/zengin/scripts/extenders/lego/tools/hook_dae.md index ca82323718..eaaf3ef5d6 100644 --- a/docs/zengin/scripts/extenders/lego/tools/hook_dae.md +++ b/docs/zengin/scripts/extenders/lego/tools/hook_dae.md @@ -1,3 +1,7 @@ +--- +title: HookDaedalus +description: LeGo package for hooking daedalus script functions +--- # HookDaedalus This package allows hooking daedalus functions. The principle is similar [HookEngine](hook_engine.md). We have a function (hooked function) into which we would like to hook another function (hook function). @@ -22,6 +26,18 @@ func void HookDaedalusFunc(var func hooked, var func hook) ``` **Parameters** +- `#!dae var func hooked` + Hooked function +- `#!dae var func hook` + Hook function + +### `HookDaedalusFuncF` +Alias to the `HookDaedalusFunc` function. +```dae +func void HookDaedalusFuncF(var func hooked, var func hook) +``` +**Parameters** + - `#!dae var func hooked` Hooked function - `#!dae var func hook` @@ -62,6 +78,7 @@ func int IsHookD(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. ### `ContinueCall` @@ -77,7 +94,7 @@ func void PassArgumentI(var int i) ``` **Parameters** -- `#!dae var int i` +- `#!dae var int i` Integer argument to forward ### `PassArgumentS` @@ -87,7 +104,7 @@ func void PassArgumentS(var string s) ``` **Parameters** -- `#!dae var string s` +- `#!dae var string s` String argument to forward ### `PassArgumentN` @@ -97,7 +114,7 @@ func void PassArgumentN(var instance n) ``` **Parameters** -- `#!dae var instance n` +- `#!dae var instance n` Instance argument to forward ## Examples @@ -111,7 +128,7 @@ The functions can look like that: ```dae func void hooked() { - Print("Orginal function"); + Print("Original function"); }; func void hook() @@ -123,7 +140,7 @@ func void hook() The results should look like that ```dae Our hook -Orginal function +Original function ``` ### Hook after function @@ -135,7 +152,7 @@ The functions are also similar, but the `ContinueCall();` is called first: ```dae func void hooked() { - Print("Orginal function"); + Print("Original function"); }; func void hook() @@ -146,7 +163,7 @@ func void hook() ``` The results should look like that: ```dae -Orginal function +Original function Our hook ``` @@ -155,7 +172,7 @@ If a function to be hooked expects parameters or returns a value, our hooking fu ```dae func int hooked(var int i) { - Print("Orginal function"); + Print("Original function"); return i+1; }; diff --git a/docs/zengin/scripts/extenders/lego/tools/hook_engine.md b/docs/zengin/scripts/extenders/lego/tools/hook_engine.md index e773082597..82d480104e 100644 --- a/docs/zengin/scripts/extenders/lego/tools/hook_engine.md +++ b/docs/zengin/scripts/extenders/lego/tools/hook_engine.md @@ -1,3 +1,7 @@ +--- +title: HookEngine +description: LeGo package for hooking engine functions +--- # HookEngine This package allows you to hook anywhere in an engine function to run your own Daedalus code. @@ -22,6 +26,20 @@ func void HookEngine(var int address, var int oldInstr, var string function) ``` **Parameters** +- `#!dae var int address` + Address of an engine function to which the function should be attached. +- `#!dae var int oldInstr` + The length in bytes of the instruction to be found at `address`, at least 5 bytes. Can be seen in IDA. +- `#!dae var string function` + Name of Daedalus function to be called. + +### `HookEngineS` +Alias to the `HookEngine` function. +```dae +func void HookEngineS(var int address, var int oldInstr, var string function) +``` +**Parameters** + - `#!dae var int address` Address of an engine function to which the function should be attached. - `#!dae var int oldInstr` @@ -226,3 +244,17 @@ Simple function to replace `return TRUE` in hook. ```dae func void Hook_ReturnTrue() ``` + +## Registers +In addition the HookEngine package implement x86 32-bit registers that can be used to access hooked function parameters. + +```dae +var int EAX; +var int ECX; +var int EDX; +var int EBX; +var int ESP; +var int EBP; +var int ESI; +var int EDI; +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/int64.md b/docs/zengin/scripts/extenders/lego/tools/int64.md index 8af97f6def..dac5056ab3 100644 --- a/docs/zengin/scripts/extenders/lego/tools/int64.md +++ b/docs/zengin/scripts/extenders/lego/tools/int64.md @@ -1,3 +1,7 @@ +--- +title: Int64 +description: LeGo package implementing 64 bit integer support +--- # Int64 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. diff --git a/docs/zengin/scripts/extenders/lego/tools/interface.md b/docs/zengin/scripts/extenders/lego/tools/interface.md new file mode 100644 index 0000000000..eda160bd2c --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/interface.md @@ -0,0 +1,704 @@ +--- +title: Interface +description: LeGo package for working with the 2D interface +--- +# Interface +This package offers a lot of useful functions to work with the 2D interface. + +## Dependencies + +- [AI_Function](ai_function.md) +- [Anim8](../applications/anim8.md) +- [HookEngine](hook_engine.md) +- [PermMem](permmem.md) + + +## Initialization +Initialize with `LeGo_Interface` and `LeGo_PrintS` flag. +```dae +LeGo_Init(LeGo_Interface | LeGo_PrintS); +``` + +## Implementation +[:material-github: Interface.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/Interface.d) + +## Functions + +### `sysGetTime` +Better alternative for `MEM_GetSysTime()` from [Ikarus](../../ikarus/index.md). +```dae +func int sysGetTime() +``` +**Return value** + +The function returns elapsed time since game (system) startup. + +### `RGBA` +Generates a full `zColor`. +```dae +func int RGBA(var int r, var int g, var int b, var int a) +``` +**Parameters** + +- `#!dae var int r` + Red channel value (0..255) +- `#!dae var int g` + Green channel value (0..255) +- `#!dae var int b` + Blue channel value (0..255) +- `#!dae var int a` + Alpha (0..255, 0 = invisible) + +**Return value** + +The function returns a `zColor` object. + +### `ChangeAlpha` +Overrides the alpha value of a given `zColor`. +```dae +func int ChangeAlpha(var int zCol, var int a) +``` +**Parameters** + +- `#!dae var int zCol` + `zColor` to modify +- `#!dae var int a` + New alpha value + +**Return value** + +The function returns a modified `zColor` object. + +### `GetAlpha` +Returns the alpha value of a given `zColor`. +```dae +func int GetAlpha(var int zCol) +``` +**Parameters** + +- `#!dae var int zCol` + `zColor` to get alpha from + +### `Print_CreateText` +Creates a new `zCViewText` on the screen with PermMem that can be freely edited. +```dae +func int Print_CreateText(var string text, var string font) +``` +**Parameters** + +- `#!dae var string text` + The text of the `zCViewText` +- `#!dae var string font` + Font of text + +**Return value** + +The function returns a handle to `zCViewText`. + +### `Print_CreateTextPtr` +`Print_CreateText` but returns pointer to `zCViewText` instead of handle. +```dae +func int Print_CreateTextPtr(var string text, var string font) +``` +**Parameters** + +- `#!dae var string text` + The text of the `zCViewText` +- `#!dae var string font` + Font of text + +**Return value** + +The function returns a pointer to `zCViewText`. + +### `Print_CreateTextPtrColored` +`Print_CreateTextPtr` but with additional parameter to chose color of text. +```dae +func int Print_CreateTextPtrColored(var string text, var string font, var int color) +``` +**Parameters** + +- `#!dae var string text` + The text of the `zCViewText` +- `#!dae var string font` + Font of text +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function + +**Return value** + +The function returns a pointer to `zCViewText`. + +### `Print_GetText` +Returns `zCViewText` instance from handle. +```dae +func zCViewText Print_GetText(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle to `zCViewText` + +### `Print_GetTextPtr` +Returns `zCViewText` pointer from handle. +```dae +func int Print_GetTextPtr(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle to `zCViewText` + +### `Print_DeleteText` +Removes a `zCViewText` from the screen. +```dae +func void Print_DeleteText(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle to `zCViewText` (form [`Print_CreateText`](#print_createtext) or [`Print_Ext`](#print_ext)) + +### `Print_SetAlpha` +Changes the alpha value of a given `zCViewText`. +```dae +func void Print_SetAlpha(var int hndl, var int a) +``` +**Parameters** + +- `#!dae var int hndl` + Handle to `zCViewText` +- `#!dae var int a` + New alpha value + +### `PrintPtr_SetAlpha` +`Print_SetAlpha` but with pointer to `zCViewText` instead of handle. +```dae +func void PrintPtr_SetAlpha(var int ptr, var int a) +``` +**Parameters** + +- `#!dae var int ptr` + Pointer to `zCViewText` +- `#!dae var int a` + New alpha value + +### `Print_GetScreenSize` +Writes the current resolution to the Print_Screen array and the current aspect ratio to Print_Ratio variable. +```dae +func void Print_GetScreenSize() +``` + +#### `Print_Screen` +An int array holding the current resolution. (Filled by `Print_GetScreenSize`) +```dae +int Print_Screen[2]; +``` + +- `Print_Screen[PS_X]` is the horizontal resolution + +- `Print_Screen[PS_Y]` is the vertical resolution + +#### `Print_Ratio` +A float variable that holds the current aspect ratio. (Filled by `Print_GetScreenSize`) +```dae +int Print_Ratio; +``` + +#### `PS_VMax` +An int constant that holds the highest possible value of a virtual coordinate. +```dae +const int PS_VMax = 8192; +``` + +### `Print_ToVirtual` +Convents pixel position to a virtual position. +```dae +func int Print_ToVirtual(var int pxl, var int dim) +``` +**Parameters** + +- `#!dae var int pxl` + Pixel position to convert +- `#!dae var int dim` + PS_X or PS_Y (see [`Print_Screen`](#print_screen)) + +**Return value** + +The function returns a virtual position of a given pixel position. + +### `Print_ToVirtualF` +`Print_ToVirtual` but returns Ikarus float value instead of integer. +```dae +func int Print_ToVirtualF(var int pxl, var int dim) +``` +**Parameters** + +- `#!dae var int pxl` + Pixel position to convert +- `#!dae var int dim` + PS_X or PS_Y (see [`Print_Screen`](#print_screen)) + +**Return value** + +The function returns a virtual position of a given pixel position as Ikarus float. + +### `Print_ToPixel` +Convents virtual position to a pixel position. +```dae +func int Print_ToPixel(var int vrt, var int dim) +``` +**Parameters** + +- `#!dae var int vrt` + Virtual position to convert +- `#!dae var int dim` + PS_X or PS_Y (see [`Print_Screen`](#print_screen)) + +**Return value** + +The function returns a pixel position of a given virtual position. + +### `Print_ToPixelF` +`Print_ToPixel` but returns Ikarus float value instead of integer. +```dae +func int Print_ToPixelF(var int vrt, var int dim) +``` +**Parameters** + +- `#!dae var int vrt` + Virtual position to convert +- `#!dae var int dim` + PS_X or PS_Y (see [`Print_Screen`](#print_screen)) + +**Return value** + +The function returns a pixel position of a given virtual position as Ikarus float. + +### `Print_ToRatio` +Gets the size in the specified dimension in ratioed by the screen. +```dae +func int Print_ToRatio(var int size, var int dim) +``` +**Parameters** + +- `#!dae var int size` + Size to convert +- `#!dae var int dim` + PS_X or PS_Y (see [`Print_Screen`](#print_screen)) + +**Return value** + +The function returns size correctly calculated to the ratio. + +??? abstract "Example" + If you have a view and the view you need to be a square of 400 units, you would do: + ```dae + height = Print_ToRatio(400, PS_Y); + width = 400; + ``` + 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. + +### `Print_ToRadian` +Converts angle in degrees to radians. +```dae +func int Print_ToRadian(var int angle) +``` +**Parameters** + +- `#!dae var int angle` + Angle in degrees + +**Return value** + +The function returns calculated angle in radians. + +### `Print_ToDegree` +Converts angle in radians to degrees. +```dae +func int Print_ToDegree(var int angle) +``` +**Parameters** + +- `#!dae var int angle` + Angle in radians + +**Return value** + +The function returns calculated angle in degrees. + +### `Print_GetFontPtr` +Returns a pointer to a `zCFont` by its name. +```dae +func int Print_GetFontPtr(var string font) +``` +**Parameters** + +- `#!dae var string font` + Name of font + +### `Print_GetFontName` +Returns a name of a `zCFont` from its pointer. +```dae +func string Print_GetFontName(var int fontPtr) +``` +**Parameters** + +- `#!dae var int fontPtr` + Pointer to font + +### `Print_GetStringWidth` +Returns the width of a string in pixels. +```dae +func int Print_GetStringWidth(var string s, var string font) +``` +**Parameters** + +- `#!dae var string s` + Measured string +- `#!dae var string font` + Name of font + +### `Print_GetStringWidthPtr` +`Print_GetStringWidth` but with `zCFont` pointer instead of name. +```dae +func int Print_GetStringWidthPtr(var string s, var int font) +``` +**Parameters** + +- `#!dae var string s` + Measured string +- `#!dae var int font` + `zCFont` pointer + +### `Print_GetFontHeight` +Returns the height of a string in pixels. +```dae +func int Print_GetFontHeight(var string font) +``` +**Parameters** + +- `#!dae var string font` + Name of font + +### `Print_Ext` +Like the external `PrintScreen`, writes a text on the screen, but with more options. +```dae +func int Print_Ext(var int x, var int y, var string text, var string font, var int color, var int time) +``` +**Parameters** + +- `#!dae var int x` + X coordinate on the screen (virtual) +- `#!dae var int y` + Y coordinate on the screen (virtual) +- `#!dae var string text` + Displayed text +- `#!dae var string font` + Name of font +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function +- `#!dae 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. + +??? abstract "Example" + ```dae + func void Example1() + { + // x, y, text, font, color, time + Print_ExtPxl(2, 2, "Text", FONT_Screen, RGBA(255, 0, 0, 128), 500); + }; + ``` + +### `Print_ExtPxl` +`Print_Ext` but with pixel coordinates instead of virtual. +```dae +func int Print_ExtPxl(var int x, var int y, var string text, var string font, var int color, var int time) +``` +**Parameters** + +- `#!dae var int x` + X coordinate on the screen (pixel) +- `#!dae var int y` + Y coordinate on the screen (pixel) +- `#!dae var string text` + Displayed text +- `#!dae var string font` + Name of font +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function +- `#!dae 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. + +### `Print_LongestLine` +Returns the longest line from `text` as a string, using default line separator tilde `~`. +```dae +func string Print_LongestLine(var string text, var string font) +``` +**Parameters** + +- `#!dae var string text` + Measured text +- `#!dae var string font` + Name of font + +### `Print_LongestLineExt` +Returns the longest line from `text` as a string, but you specify new line separator. +```dae +func string Print_LongestLineExt(var string text, var string font, var string separator) +``` +**Parameters** + +- `#!dae var string text` + Measured text +- `#!dae var string font` + Name of font +- `#!dae var string separator` + New line separator + +### `Print_LongestLineLength` +Returns the longest line width in pixels, using default line separator tilde `~`. +```dae +func int Print_LongestLineLength(var string text, var string font) +``` +**Parameters** + +- `#!dae var string text` + Measured text +- `#!dae var string font` + Name of font + +### `Print_LongestLineLengthExt` +Returns the longest line width in pixels, but allows you to specify new line separator. +```dae +func int Print_LongestLineLengthExt(var string text, var string font, var string separator) +``` +**Parameters** + +- `#!dae var string text` + Measured text +- `#!dae var string font` + Name of font +- `#!dae var string separator` + New line separator + +### `Print_TextField` +Creates a text field (view with text) using virtual coordinates. +```dae +func int Print_TextField(var int x, var int y, var string text, var string font, var int height) +``` +**Parameters** + +- `#!dae var int x` + X coordinate (virtual) +- `#!dae var int y` + Y coordinate (virtual) +- `#!dae var string text` + Text to be printed +- `#!dae var string font` + Name of font +- `#!dae var int height` + A specific line `height` + +**Return value** + +The function returns a text field pointer. Here is how it is used: +```dae +var zCView view; view = get(viewHndl); +view.textLines_next = Print_TextField(x, y, text, FONT, fontHeight); +``` + +### `Print_TextFieldPxl` +`Print_TextField` but with pixel coordinates. +```dae +func int Print_TextFieldPxl(var int x, var int y, var string text, var string font) +``` +**Parameters** + +- `#!dae var int x` + X coordinate (pixel) +- `#!dae var int y` + Y coordinate (pixel) +- `#!dae var string text` + Text to be printed +- `#!dae 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. + +### `Print_TextFieldColored` +`Print_TextField` but you specify the color of text. +```dae +func int Print_TextFieldColored(var int x, var int y, var string text, var string font, var int height, var int color) +``` +**Parameters** + +- `#!dae var int x` + X coordinate (virtual) +- `#!dae var int y` + Y coordinate (virtual) +- `#!dae var string text` + Text to be printed +- `#!dae var string font` + Name of font +- `#!dae var int height` + A specific line `height` +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function + +**Return value** + +The function returns a text field pointer. Look at the `Print_TextField` return value to see an example. + +### `PrintS` +Same function as the external `Print`, but with smooth animations. The effect can be changed as desired with the [user constants](../various/userconstants.md#prints). +```dae +func void PrintS(var string txt) +``` +**Parameters** + +- `#!dae var string txt` + Printed text + +### `PrintS_Ext` +`PrintS` but with an additional parameter to choose the color of the text. +```dae +func void PrintS_Ext(var string txt, var int color) +``` +**Parameters** + +- `#!dae var string txt` + Printed text +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function + +### `AI_PrintS` +Version of `PrintS` that enqueue in given NPCs AI queue. +```dae +func void AI_PrintS(var c_npc slf, var string txt) +``` +**Parameters** + +- `#!dae var c_npc slf` + NPC to whose AI queue the function is enqueued +- `#!dae var string txt` + Printed text + +### `AI_PrintS_Ext` +Version of `PrintS_Ext` that enqueue in given NPCs AI queue. +```dae +func void AI_PrintS_Ext(var c_npc slf, var string txt, var int color) +``` +**Parameters** + +- `#!dae var c_npc slf` + NPC to whose AI queue the function is enqueued +- `#!dae var string txt` + Printed text +- `#!dae var int color` + `zColor` e.g. generated with [RGBA](#rgba) function + +## Examples + +### Manage a print via zCViewText +It is also possible to create the text only via [Print_CreateText](#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](../applications/anim8.md): +```dae +var int MyText; +var int MyAnim8; +func void PrintMyScrollingText(var string text) { + MyText = Print_CreateText(text, FONT_Screen); // We create an empty text item with the font FONT_Screen + + var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Now we get the empty text item in a zCViewText + + MyTextObject.posx = 1; // adjust position + MyTextObject.posy = 1; // ATTENTION: These values are virtual, i.e.: 0 = far left, 8192 = far right (i.e. no pixel specification) + // (But if I prefer to have pixel coordinates I could use e.g. Print_ToVirtual) + MyTextObject.timed = false; // The text should not be timed (not disappear) + + // Anim8 will animate a text + // First we need a new Anim8 object: + MyAnim8 = Anim8_New(1, false); // Start position is 1 and this value is not a float + + Anim8(MyAnim8, 8192, 2000, A8_Constant); // Target Position is 8192, Duration is 2000 milliseconds, and Movement Form is Constant + + // Now all we need is a loop that matches the x value of the text to the value of Anim8: + FF_Apply(ScrollMyText); +}; + +func void ScrollMyText() { + var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); // Get the text as an object again + + // And now compare the values: + MyTextObject.posx = Anim8_Get(MyAnim8); + + // When Anim8 is done with that, we end the loop and delete the text: + if(Anim8_Empty(MyAnim8)) { + Print_DeleteText(MyText); + FF_Remove(ScrollMyText); + // The Anim8 object must of course also be deleted. We don't need it anymore. + Anim8_Delete(MyAnim8); + }; +}; +``` + +### Manage a print via zCViewText with LeGo 2.2+ +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: +```dae +var int MyText; +var int MyAnim8; +func void PrintMyScrollingText(var string text) { + // Create and set text: + MyText = Print_CreateText(text, FONT_Screen); + + var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); + + MyTextObject.posx = 1; + MyTextObject.posy = 1; + + MyTextObject.timed = false; + + // But now comes the trick: We use Anim8_NewExt, this allows us to set a "Handler" and "Data". + MyAnim8 = Anim8_NewExt(1, ScrollMyText, MyText, false); + + // ScrollMyText is passed as the handler and MyText as the data. + // In concrete terms, this means: ScrollMyText is always called + // when Anim8 has recalculated the position. + // Pass data and the new position as parameters. Let's see how it goes. + + // Set the animation again as usual: + Anim8(MyAnim8, 8192, 2000, A8_Constant); + + // And this time no FrameFunction. + // Instead, we tell Anim8 to clean up by itself when it's done: + Anim8_RemoveIfEmpty(MyAnim8, true); + + // The text should also disappear by itself: + Anim8_RemoveDataIfEmpty(MyAnim8, true); + + // Since MyText is a handle, this will work. + // If MyText were a pointer, RemoveDataIfEmpty should not be activated, it would lead to an error message. +}; + +func void ScrollMyText(var int MyText, var int Position) { + // Get the text as an object again + var zCViewText MyTextObject; MyTextObject = Print_GetText(MyText); + + // And now compare the values: + MyTextObject.posx = Position; + + // Since Anim8 does the deleting itself, we don't have to worry about that. +}; +``` diff --git a/docs/zengin/scripts/extenders/lego/tools/item_helper.md b/docs/zengin/scripts/extenders/lego/tools/item_helper.md index e6c2482de7..1e0c374b18 100644 --- a/docs/zengin/scripts/extenders/lego/tools/item_helper.md +++ b/docs/zengin/scripts/extenders/lego/tools/item_helper.md @@ -1,3 +1,7 @@ +--- +title: ItemHelper +description: LeGo package that makes changing `C_ITEM` instance to `oCItem` pointer possible +--- # ItemHelper This package is very simple - it retrieves a `oCItem` pointer from an `C_ITEM` instance valid for the current world and session. @@ -16,9 +20,9 @@ N/A ## Functions -### `ITM_GetPtr` +### `Itm_GetPtr` ```dae -func int ITM_GetPtr(var int instance) +func int Itm_GetPtr(var int instance) ``` **Parameters** diff --git a/docs/zengin/scripts/extenders/lego/tools/item_helper.pl.md b/docs/zengin/scripts/extenders/lego/tools/item_helper.pl.md index f025953a4c..b76263bb24 100644 --- a/docs/zengin/scripts/extenders/lego/tools/item_helper.pl.md +++ b/docs/zengin/scripts/extenders/lego/tools/item_helper.pl.md @@ -1,5 +1,6 @@ --- title: ItemHelper +description: Pakiet LeGo umożliwiający zmianę instancji `C_ITEM` na pointer `oCItem` --- # ItemHelper - pomocnik do przedmiotów Ten pakiet jest bardzo prosty - pobiera wskaźnik `oCItem` z instancji `C_ITEM` ważnej dla bieżącego świata i sesji. @@ -19,9 +20,9 @@ Nie dotyczy. ## Funkcje -### `ITM_GetPtr` +### `Itm_GetPtr` ```dae -func int ITM_GetPtr(var int instance) +func int Itm_GetPtr(var int instance) ``` **Parametry** diff --git a/docs/zengin/scripts/extenders/lego/tools/list.md b/docs/zengin/scripts/extenders/lego/tools/list.md new file mode 100644 index 0000000000..2512ac66a8 --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/list.md @@ -0,0 +1,383 @@ +--- +title: List +description: LeGo package implementing `zCList` and `zCListSort` data types handling +--- +# List +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. + +## Dependencies +N/A + +## Initialization +N/A + +## Implementation +[:material-github: List.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/List.d) + +## Functions +!!! 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! + +### `List_Create` +Creates a list with an initial value. +```dae +func int List_Create(var int data) +``` +**Parameters** + +- `#!dae var int data` + The value of the first list element. + +**Return value** + +The function returns a pointer to the created list. + +### `List_Add` +Appends a value to the end of the list. +```dae +func void List_Add(var int list, var int data) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int data` + The value to be appended. + +### `List_AddFront` +Adds a value before the first element of the list. +```dae +func void List_AddFront(var int list, var int data) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int data` + The value to be appended. + +### `List_AddOffset` +Inserts a value between two list elements. +```dae +func void List_AddOffset(var int list, var int offset, var int data) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int offset` + The number of the list element after which the value is inserted. +- `#!dae var int data` + The value to be appended. + +### `List_Set` +Sets a list element to a specific value. +```dae +func void List_Set(var int node, var int data) +``` +**Parameters** + +- `#!dae var int node` + Pointer to a list element. +- `#!dae var int data` + The value to be written into the list element. + +### `List_Get` +Retrieves the value of a list element. +```dae +func int List_Get(var int list, var int nr) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int nr` + The number of the list element. + +**Return value** + +The function returns the value of the specified list element. + +### `List_Node` +Returns a pointer to a list element. +```dae +func int List_Node(var int list, var int nr) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int nr` + The number of a list element. + +**Return value** + +The function returns a pointer to the specified list element. + +### `List_Length` +Returns the length of the list (number of all elements). +```dae +func int List_Length(var int list) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. + +**Return value** + +The function returns the number of elements in the list. + +### `List_HasLength` +Checks if the list has the specified length. +```dae +func int List_HasLength(var int list, var int length) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int length` + The desired length. + +**Return value** + +The function returns a boolean value indicating whether the list has the specified length or not. + +### `List_End` +Returns the last list element of the list. +```dae +func int List_End(var int list) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. + +**Return value** + +The function returns a pointer to the last list element. + +### `List_Concat` +Concatenates two lists. +```dae +func void List_Concat(var int list, var int list2) +``` +**Parameters** + +- `#!dae var int list` + The first list. +- `#!dae var int list2` + The second list. Its beginning is appended to the end of the first list. + +### `List_Contains` +Returns the last list element with a specific value. +```dae +func int List_Contains(var int list, var int data) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int data` + The value to search for. + +**Return value** + +The function returns the number of the last list element with the value `data`. + +### `List_For` +Calls a function for each list element, passing a pointer to the list element as a parameter. +```dae +func void List_For(var int list, var string function) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var string function` + Name of a function to be called for each list element (`void handler(var int node)`). + +### `List_ForF` +Similar to `List_For`, but with a function parameter instead of a string. +```dae +func void ListForF(var int list, var func function) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var func function` + The function to be called for each list element (`void handler(var int node)`). + +### `List_ForI` +Similar to `List_For`, but with a function parameter instead of a string. +```dae +func void List_ForI(var int list, var int funcID) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int funcID` + ID of a function to be called for each list element (`void handler(var int node)`). + +### `List_Delete` +Deletes a list element. All subsequent elements shift position. +```dae +func void List_Delete(var int list, var int nr) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. +- `#!dae var int nr` + The number of the list element to be deleted. + + +### `List_Destroy` +Destroys the entire list. +```dae +func void List_Destroy(var int list) +``` +**Parameters** + +- `#!dae var int list` + The list to be destroyed. + +### `List_ToArray` +Returns a pointer to a memory area containing all values of the list. +```dae +func int List_ToArray(var int list) +``` +**Parameters** + +- `#!dae var int list` + The list to be used. + +**Return value** + +The function returns a memory area containing all the values of the list. + +### `List_MoveDown` +Moves the specified list node down by one position in the list. +```dae +func void List_MoveDown(var int list, var int node) +``` +**Parameters** + +- `#!dae var int list` + The list in which the node is located. +- `#!dae var int node` + The node to be moved down. + +### `List_MoveUp` +Moves the specified list node up by one position in the list. +```dae +func void List_MoveUp(var int list, var int node) +``` +**Parameters** + +- `#!dae var int list` + The list in which the node is located. +- `#!dae var int node` + The node to be moved up. + +### `List_InsertSorted` +Inserts a value into a sorted list while preserving the sort order. + +```dae +func void List_InsertSorted(var int list, var int data, var func compare) +``` +**Parameters:** + +- `#!dae var int list` + The list to insert the value into. +- `#!dae var int data` + The value to be inserted. +- `#!dae var func compare` + A comparison function used to determine the sort order. + +### `List_Compare` +```dae +func int List_Compare(var int data1, var int data2, var func compare) +``` +**Parameters:** + +- `#!dae var int data1` + The first integer value. +- `#!dae var int data2` + The second integer value. +- `#!dae var func compare` + One of comparison functions. +**Return value** + +The function returns the return value of specified comparison function. + +## Comparison Functions + +The following comparison functions can be used as the `compare` parameter in the `List_InsertSorted` and `List_Compare` function: + +#### `List_CmpAscending` +Compares two integer values in ascending order. +```dae +func int List_CmpAscending(var int data1, var int data2) +``` +**Parameters:** + +- `#!dae var int data1` + The first integer value. +- `#!dae var int data2` + The second integer value. + +**Return Value:** + +The function returns `TRUE` if `data1` is greater than `data2`, `FALSE` is returned otherwise. + +#### `List_CmpDescending` +Compares two integer values in descending order. +```dae +func int List_CmpDescending(var int data1, var int data2) +``` +**Parameters:** + +- `#!dae var int data1` + The first integer value. +- `#!dae var int data2` + The second integer value. + +**Return Value:** + +The function returns `TRUE` if `data1` is less than `data2`, `FALSE` is returned otherwise. + +#### `List_CmpAscendingUnsigned` +Compares two unsigned integer values in ascending order. +```dae +func int List_CmpAscendingUnsigned(var int data1, var int data2) +``` +**Parameters:** + +- `#!dae var int data1` + The first unsigned integer value. +- `#!dae var int data2` + The second unsigned integer value. + +**Return Value:** + +The function returns `TRUE` if `data1` is greater than `data2`, `FALSE` is returned otherwise. + +#### `List_CmpDescendingUnsigned` +Compares two unsigned integer values in descending order. +```dae +func int List_CmpDescendingUnsigned(var int data1, var int data2) +``` +**Parameters:** + +- `#!dae var int data1` + The first unsigned integer value. +- `#!dae var int data2` + The second unsigned integer value. + +**Return Value:** + +The function returns `TRUE` if `data1` is less than `data2`, `FALSE` is returned otherwise. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/locals.md b/docs/zengin/scripts/extenders/lego/tools/locals.md index d5b73767a9..fcc41fcf7b 100644 --- a/docs/zengin/scripts/extenders/lego/tools/locals.md +++ b/docs/zengin/scripts/extenders/lego/tools/locals.md @@ -1,3 +1,7 @@ +--- +title: Locals +description: LeGo package adding true local variables and final clause +--- # Locals 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. @@ -5,7 +9,7 @@ There is also the `final` function, which can be used to emulate something simil ## Dependencies -- StringBuilder +- [StringBuilder](string_builder.md) ## Initialization N/A @@ -27,7 +31,7 @@ It is hard to explain how to use it, but very easy to understand once you've see func int Final() ``` -??? abstract "Examples" +??? abstract "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. ```dae func void testFinal() diff --git a/docs/zengin/scripts/extenders/lego/tools/misc.md b/docs/zengin/scripts/extenders/lego/tools/misc.md index ae0db1e2f2..f20b55745c 100644 --- a/docs/zengin/scripts/extenders/lego/tools/misc.md +++ b/docs/zengin/scripts/extenders/lego/tools/misc.md @@ -1,9 +1,13 @@ +--- +title: Misc +description: LeGo package implementing various helper functions +--- # Misc - The Misc package introduces various helper functions that did not fit into any other package. ## Dependencies -N/A + +- [Floats](../../ikarus/floats.md) ## Initialization N/A @@ -11,12 +15,21 @@ N/A ## Implementation [:material-github: Misc.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/Misc.d) +## Constants +Misc package implements the `phi` constant +```dae +const int phi = 1070141312; // PI/2 +``` +which is actually `pi` divided by 2 saved as an ikarus float. + +Decimal: `1.5707...` + ## Functions ### `atan2f` Calculates the arcus tangent of an angle between the origin and (x, y) point. ```dae -func float atan2f(var int x, var int y) +func int atan2f(var int x, var int y) ``` **Parameters** @@ -32,73 +45,73 @@ The function returns arcus tangent in radians as Ikarus `float`. ### `sin` Calculates the sine of an angle given in radians. ```dae -func float sin(var float angle) +func int sin(var int angle) ``` **Parameters** -- `#!dae var float angle` +- `#!dae var int angle` The angle in radians as a Ikarus `float` **Return value** -The function returns sine of the angle. +The function returns sine of the angle as Ikarus `float`. ### `cos` Calculates the cosine of an angle given in radians. ```dae -func float cos(var float angle) +func int cos(var int angle) ``` **Parameters** -- `#!dae var float angle` +- `#!dae var int angle` The angle in radians as a Ikarus `float` **Return value** -The function returns cosine of the angle. +The function returns cosine of the angle as Ikarus `float`. ### `tan` Calculates the tangent of an angle given in radians. ```dae -func float tan(var float angle) +func int tan(var int angle) ``` **Parameters** -- `#!dae var float angle` +- `#!dae var int angle` The angle in radians as a Ikarus `float` **Return value** -The function returns tangent of the angle. +The function returns tangent of the angle as Ikarus `float`. ### `asin` -Calculates the arcus sine +Calculates the arcus sine. ```dae -func float asin(var float sine) +func int asin(var int sine) ``` **Parameters** -- `#!dae var float sine` +- `#!dae var int sine` The sine of an angle as a Ikarus `float` **Return value** -The function returns arcus sine of the angle. +The function returns arcus sine of the angle as Ikarus `float`. ### `acos` Calculates the arcus cosine ```dae -func float acos(var float cosine) +func int acos(var int cosine) ``` **Parameters** -- `#!dae var float cosine` +- `#!dae var int cosine` The cosine of an angle as a Ikarus `float` **Return value** -The function returns arcus cosine of the angle. +The function returns arcus cosine of the angle as Ikarus `float`. ### `distance2D` @@ -124,17 +137,17 @@ The function returns the distance between the two points. ### `distance2Df` Calculates the distance between two points on a two-dimensional plane but parameters and return values are Ikarus `floats`. ```dae -func float distance2Df(var float x1, var float x2, var float y1, var float y2) +func int distance2Df(var int x1, var int x2, var int y1, var int y2) ``` **Parameters** -- `#!dae var float x1` +- `#!dae var int x1` X-coordinate of the first point -- `#!dae var float x2` +- `#!dae var int x2` X-coordinate of the second point -- `#!dae var float y1` +- `#!dae var int y1` Y-coordinate of the first point -- `#!dae var float y2` +- `#!dae var int y2` Y-coordinate of the second point **Return value** diff --git a/docs/zengin/scripts/extenders/lego/tools/misc.pl.md b/docs/zengin/scripts/extenders/lego/tools/misc.pl.md index 2483feef7b..15cf87044e 100644 --- a/docs/zengin/scripts/extenders/lego/tools/misc.pl.md +++ b/docs/zengin/scripts/extenders/lego/tools/misc.pl.md @@ -1,5 +1,6 @@ --- -title: Różne +title: Misc +description: Pakiet LeGo implementujący różne funkcje pomocnicze --- # Misc - różne Pakiet Misc wprowadza różne funkcje pomocnicze, które nie pasowały do żadnego innego pakietu. @@ -13,12 +14,22 @@ Nie dotyczy. ## Implementacja [:material-github: Misc.d na GitHubie](https://github.com/Lehona/LeGo/blob/dev/Misc.d) +## Stałe +Pakiet Misc implementuje satłą `phi` +```dae +const int phi = 1070141312; // PI/2 +``` +która w rzeczywistości jest liczbą `pi` podzieloną przez 2 zapisaną jako ikarusowy float. + +Decymalnie: `1.5707...` + + ## Funkcje ### `atan2f` Oblicza arcus tangens kąta między początkiem a punktem (x, y). ```dae -func float atan2f(var int x, var int y) +func int atan2f(var int x, var int y) ``` **Parametry** @@ -29,78 +40,78 @@ func float atan2f(var int x, var int y) **Zwracana wartość** -Funkcja zwraca arcus tangens w radianach jako ikarusowy `float` +Funkcja zwraca arcus tangens w radianach, jako ikarusowy `float`. ### `sin` Oblicza sinus kąta podanego w radianach. ```dae -func float sin(var float angle) +func int sin(var int angle) ``` **Parametry** -- `#!dae var float angle` +- `#!dae var int angle` Kąt w radianach jako ikarusowy `float` **Zwracana wartość** -Funkcja zwraca sinus kąta. +Funkcja zwraca sinus kąta, jako ikarusowy `float`. ### `cos` Oblicza cosinus kąta podanego w radianach. ```dae -func float cos(var float angle) +func int cos(var int angle) ``` **Parametry** -- `#!dae var float angle` +- `#!dae var int angle` Kąt w radianach jako ikarusowy `float` **Zwracana wartość** -Funkcja zwraca cosinus kąta. +Funkcja zwraca cosinus kąta, jako ikarusowy `float`. ### `tan` Oblicza tangens kąta podanego w radianach. ```dae -func float tan(var float angle) +func int tan(var int angle) ``` **Parametry** -- `#!dae var float angle` +- `#!dae var int angle` Kąt w radianach jako ikarusowy `float` **Zwracana wartość** -Funkcja zwraca tangens kąta. +Funkcja zwraca tangens kąta, jako ikarusowy `float`. ### `asin` Oblicza arcus sinus ```dae -func float asin(var float sine) +func int asin(var int sine) ``` **Parametry** -- `#!dae var float sine` +- `#!dae var int sine` Sinus kąta jako ikarusowy `float` **Zwracana wartość** -Funkcja zwraca arcus sinus kąta. +Funkcja zwraca arcus sinus kąta, jako ikarusowy `float`. ### `acos` Oblicza arcus cosinus ```dae -func float acos(var float cosine) +func int acos(var int cosine) ``` **Parametry** -- `#!dae var float cosine` +- `#!dae var int cosine` Cosinus kąta jako ikarusowy `float` **Zwracana wartość** -Funkcja zwraca arcus cosinus kąta. +Funkcja zwraca arcus cosinus kąta, jako ikarusowy `float`. ### `distance2D` @@ -127,17 +138,17 @@ Funkcja zwraca odległość między dwoma punktami. ### `distance2Df` Oblicza odległość między dwoma punktami na płaszczyźnie dwuwymiarowej, ale na liczbach zmiennoprzecinkowych (float). ```dae -func float distance2Df(var float x1, var float x2, var float y1, var float y2) +func int distance2Df(var int x1, var int x2, var int y1, var int y2) ``` **Parametry** -- `#!dae var float x1` +- `#!dae var int x1` współrzędna x pierwszego punktu -- `#!dae var float x2` +- `#!dae var int x2` współrzędna x drugiego punktu -- `#!dae var float y1` +- `#!dae var int y1` współrzędna y pierwszego punktu -- `#!dae var float y2` +- `#!dae var int y2` współrzędna y drugiego punktu **Zwracana wartość** diff --git a/docs/zengin/scripts/extenders/lego/tools/permmem.md b/docs/zengin/scripts/extenders/lego/tools/permmem.md new file mode 100644 index 0000000000..a32df568ac --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/permmem.md @@ -0,0 +1,515 @@ +--- +title: PermMem +description: LeGo package implementing automatic instances saving and loading +--- +# PermMem +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. + +## Dependencies + +- [Saves](../applications/saves.md) +- [Locals](locals.md) + +## Initialization +Initialize with `LeGo_PermMem` flag. +```dae +LeGo_Init(LeGo_PermMem); +``` + +## Implementation +[:material-github: PermMem.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/PermMem.d) + +## Functions + +### `new` +Creates a handle to a new instance of `inst`. +```dae +func int new(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + A valid instance. Used as "constructor" + +**Return value** + +The function returns a new, valid PermMem handle. + +### `create` +Similar to [`new`](#new), but here a pointer is returned directly and not a handle. Caution! Not managed by PermMem! +```dae +func int create(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + A valid instance. Used as "constructor" + +**Return value** + +The function returns a pointer to the new instance. + +### `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. +```dae +func int wrap(var int inst, var int ptr) +``` +**Parameters** + +- `#!dae var int inst` + A valid instance. Determines the type of the handle +- `#!dae var int ptr` + Pointer to wrap + +**Return value** + +The function returns a handle with `ptr` as content. + +### `clear` +Cleans the handle. After that it is invalid. +```dae +func void clear(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `release` +Frees the handle. The reserved memory is not deleted, the handle becomes invalid. +```dae +func void release(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `delete` +Cleans the handle just like [`clear`](#clear), only the destructor is also called. +```dae +func void delete(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `free` +Similar to [`delete`](#delete), only here a pointer is destroyed and not a handle. Caution! Not managed by PermMem! +```dae +func void free(var int ptr, var int inst) +``` +**Parameters** + +- `#!dae var int ptr` + The pointer to be cleaned +- `#!dae var int inst` + Instance used in [`create`](#create) function. + +### `get` +Returns the instance of the handle. +```dae +func instance get(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `getPtr` +Returns a pointer to instance of handle. +```dae +func int getPtr(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `setPtr` +Sets the pointer of a handle. +```dae +func void setPtr(var int hndl, var int ptr) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle +- `#!dae var int ptr` + New pointer for handle + +### `getInst` +Returns the instance used to create the given handle in [`new`](#new) function. +```dae +func int getInst(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Valid PermMem handle + +### `numHandles` +Returns the number of handles managed by PermMem. +```dae +func int numHandles() +``` + +### `sizeof` +Gets the size of the given instance's class. +```dae +func int sizeof(var int inst) +``` +**Parameters** + +- `#!dae var int inst` + Any instance + +**Return value** + +The function returns the size of a given instance's class in bytes. + +### `Hlp_IsValidHandle` +Indicates whether the handle exists and is managed by PermMem. +```dae +func int Hlp_IsValidHandle(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + PermMem's handle + +**Return value** + +The function returns `TRUE` if the handle is valid (managed by PermMem), `FALSE` is returned otherwise. + +??? abstract "Example" + The example function that use `Hlp_IsValidHandle` is [`Bar_SetMax`](../applications/bars.md#bar_setmax) form LeGo [Bars](../applications/bars.md) package. The function first checks if the handle is valid, then gets the instance and changes its parameters. + + ```dae + func void Bar_SetMax(var int bar, var int max) + { + if(!Hlp_IsValidHandle(bar)) { return; }; + var _bar b; b = get(bar); + b.valMax = max; + }; + ``` + +### `foreachHndl` +Executes a function for each handle of an instance. +```dae +func void foreachHndl(var int inst, var func fnc) +``` +**Parameters** + +- `#!dae var int inst` + The function is called for this instance +- `#!dae var int inst` + This function is called. The signature is `function(int handle)` + +### `hasHndl` +Checks if PermMem has a handle of this instance. +```dae +func int hasHndl(var int inst) +``` +**Parameters** + +- `#!dae 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. + +### `MEM_ReadStringArray` +Function moved to PermMem form [Ikarus](../../ikarus/functions/mem_access.md#mem_readstringarray). Reads string from the array at the `arrayAddress`. +```dae +func string MEM_ReadStringArray(var int arrayAddress, var int index) +``` +**Parameters** + +- `#!dae var int arrayAddress` + Memory address of array +- `#!dae var int offset` + Array offset (array index) + +**Return value** + +The function returns string from the array if the address is correct. + + +### `PM_Exists` +Checks if the specified field already exists in the archive. (used with archiver/unarchiver) +```dae +func int PM_Exists(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the field + +**Return value** + +The function returns `TRUE` if the field exists in the archive, `FALSE` is returned otherwise. + +## Archiver + +### `PM_SaveInt` +Saves an integer to the archive. +```dae +func void PM_SaveInt (var string name, var int val) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int val` + Value of the saved integer + +### `PM_SaveFloat` +Saves a daedalus float to the archive. +```dae +func void PM_SaveFloat (var string name, var int flt) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int flt` + Value of the saved float + +### `PM_SaveString` +Saves a string to the archive. +```dae +func void PM_SaveString (var string name, var string val) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var string val` + Saved string + +### `PM_SaveFuncID` +Saves a function ID to the archive. +```dae +func void PM_SaveFuncID(var string name, var int fnc) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int fnc` + Saved function ID + +### `PM_SaveFuncOffset` +Saves a function offset to the archive. +```dae +func void PM_SaveFuncOffset(var string name, var int fnc) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int fnc` + Saved function offset + +### `PM_SaveFuncPtr` +Saves a function pointer to the archive. +```dae +func void PM_SaveFuncPtr(var string name, var int fnc) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int fnc` + Saved function pointer + +### `PM_SaveClassPtr` +Saves a pointer of a class to the archive. +```dae +func void PM_SaveClassPtr(var string name, var int ptr, var string className) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int ptr` + Saved pointer +- `#!dae var string className` + Name of the class of stored pointer + +### `PM_SaveClass` +Saves a class like [`PM_SaveClassPtr`](#pm_saveclassptr). +```dae +func void PM_SaveClass(var string name, var int ptr, var string className) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int ptr` + Saved class pointer +- `#!dae var string className` + Name of the class of stored pointer + +### `PM_SaveIntArray` +Saves an array of integers. +```dae +func void PM_SaveIntArray(var string name, var int ptr, var int elements) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int ptr` + Pointer to the array +- `#!dae var int elements` + Number of elements in array + +### `PM_SaveStringArray` +Saves an array of integers. +```dae +func void PM_SaveStringArray(var string name, var int ptr, var int elements) +``` +**Parameters** + +- `#!dae var string name` + Name of the field in saved archive +- `#!dae var int ptr` + Pointer to the array +- `#!dae var int elements` + Number of elements in array + +## Unarchiver + +### `PM_Load` +Universal function to load integers, floats, class pointers and int arrays. +```dae +func int PM_Load(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +**Return value** +The function returns the data existing in the archive at the given field. + +### `PM_LoadInt` +Returns an integer stored in the archive. +```dae +func int PM_LoadInt(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadFloat` +Returns a daedalus float stored in the archive. +```dae +func int PM_LoadFloat(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadString` +Returns a string stored in the archive. +```dae +func string PM_LoadString(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadFuncID` +Returns a function ID stored in the archive. +```dae +func int PM_LoadFuncID(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadFuncOffset` +Returns a function offset stored in the archive. +```dae +func int PM_LoadFuncOffset(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadFuncPtr` +Returns a function pointer stored in the archive. +```dae +func int PM_LoadFuncPtr(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadClassPtr` +Returns a class pointer stored in the archive. +```dae +func int PM_LoadClassPtr(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadClass` +Loads a pointer to the class from the archive to `destPtr`. +```dae +func void PM_LoadClass(var string name, var int destPtr) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field +- `#!dae var int destPtr` + Destination pointer, the address to where it will deserialize the saved data + +### `PM_LoadArray` +Returns a pointer to array stored in the archive. +```dae +func int PM_LoadArray(var string name) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field + +### `PM_LoadArrayToPtr` +Loads a pointer to array from the archive to `destPtr`. +```dae +func void PM_LoadArrayToPtr(var string name, var int destPtr) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field +- `#!dae var int destPtr` + Destination pointer, the address to where it will deserialize the saved data + +### `PM_LoadToPtr` +Universal function to load array or class pointer from the archive to `destPtr`. +```dae +func void PM_LoadToPtr(var string name, var int destPtr) +``` +**Parameters** + +- `#!dae var string name` + Name of the loaded field +- `#!dae var int destPtr` + Destination pointer, the address to where it will deserialize the saved data \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/queue.md b/docs/zengin/scripts/extenders/lego/tools/queue.md index f60f6c6dec..f16a52283e 100644 --- a/docs/zengin/scripts/extenders/lego/tools/queue.md +++ b/docs/zengin/scripts/extenders/lego/tools/queue.md @@ -1,9 +1,13 @@ +--- +title: Queue +description: LeGo package implementing queue data structure +--- # Queue This package is an implementation of the Queue data structure and a queue for function calls. ## Dependencies -- PermMem +- [PermMem](permmem.md) ## Initialization N/A @@ -99,7 +103,7 @@ func void Q_ForF(var int queue, var func f) - `#!dae var int queue` Handle of a queue - `#!dae var func f` - This function is executed for all values in the queue (signature: void (zCList*)) + This function is executed for all values in the queue (signature: `void (zCList*)`) ## CallbackQueue @@ -188,5 +192,3 @@ func void CQ_Exhaust(var int queue) - `#!dae var int queue` Handle of a callback queue - -[//]: # (//TODO check if there are missing functions by Emu) diff --git a/docs/zengin/scripts/extenders/lego/tools/random.md b/docs/zengin/scripts/extenders/lego/tools/random.md index c0f667d86e..1b5c48d6cd 100644 --- a/docs/zengin/scripts/extenders/lego/tools/random.md +++ b/docs/zengin/scripts/extenders/lego/tools/random.md @@ -1,3 +1,7 @@ +--- +title: Random +description: LeGo package providing a better alternative for a `Hlp_Random()` function +--- # Random Provides more random randomization than `Hlp_Random()` function. diff --git a/docs/zengin/scripts/extenders/lego/tools/string_builder.md b/docs/zengin/scripts/extenders/lego/tools/string_builder.md new file mode 100644 index 0000000000..7734c54d5d --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/string_builder.md @@ -0,0 +1,329 @@ +--- +title: StringBuilder +description: LeGo package for creating strings without using a 'ConcatStrings' function +--- +# StringBuilder +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`](#sb_initbuffer), including it, use the active StringBuilder set with [`SB_New`](#sb_new) or [`SB_Use`](#sb_use), so there is no `#!dae 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. + +## Dependencies +N/A + +## Initialization +N/A + +## Implementation +[:material-github: StringBuilder.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/StringBuilder.d) + +## Functions + +### `SB_New` +Creates and returns a new `StringBuilder`. At the same time, this new `StringBuilder` is set as active. (See [`SB_Use`](#sb_use).) +```dae +func int SB_New() +``` +**Return value** + +The function returns a pointer to a new `StringBuilder`. + +### `SB_Use` +Marks this `StringBuilder` as active. It can now be used with the functions. +```dae +func void SB_Use(var int sb) +``` +**Parameters** + +- `#!dae var int sb` + Pointer to a `StringBuilder`, returned from [`SB_New`](#sb_new) + +### `SB_Get` +Returns the active `StringBuilder`. +```dae +func int SB_Get() +``` +**Return value** + +The function returns the active `StringBuilder` object - last set with [`SB_Use`](#sb_use) or just created with [`SB_New`](#sb_new). + +### `SB_InitBuffer` +If the size of the resulting string is already known, the buffer can be set manually. This is usually not necessary. +```dae +func void SB_InitBuffer(var int size) +``` +**Parameters** + +- `#!dae var int size` + Size in bytes. **Warning!** Only works if the `StringBuilder` has been newly created! + +### `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. +```dae +func void SB_Clear() +``` + +### `SB_Release` +Releases the current stream of the `StringBuilder`. The `StringBuilder` is destroyed, and the stream can be obtained via `SB_GetStream`. +```dae +func void SB_Release() +``` + +### `SB_Destroy` +Completely destroys the `StringBuilder`. +```dae +func void SB_Destroy() +``` + +### `SB_ToString` +Returns a copy of the stream as a string. +```dae +func string SB_ToString() +``` +**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. + +### `SB_ToStream` +Returns a copy of the stream in raw format. +```dae +func int SB_ToStream() +``` +**Return value** + +The function returns a copy of the stream in raw format (`char[]`) + +### `SB_GetStream` +Doesn't copy the stream, but returns it as it is. +```dae +func int SB_GetStream() +``` +**Return value** + +The function returns the stream as it is. [`SB_Destroy`](#sb_destroy) or [`SB_Clear`](#sb_clear) destroy the returned pointer. + +### `SB_Length` +Returns the current length of the stream. Similar to [`STR_Len`](../../ikarus/functions/string.md#str_len) from [Ikarus](../../ikarus/index.md) . +```dae +func int SB_Length() +``` +**Return value** + +The function returns the current length of the active `StringBuilder`. + +### `SB_SetLength` +Sets the length of the stream. When increasing, zero bytes are appended. +```dae +func void SB_SetLength(var int length) +``` + +## Stream operations + + +### `SB` +Appends a string, to the active `StringBuilder`. +```dae +func void SB(var string s) +``` +**Parameters** + +- `#!dae var string s` + The appended string + +### `SBi` +Appends an integer in text form, to the active `StringBuilder`. +```dae +func void SBi(var int i) +``` +**Parameters** + +- `#!dae var int i` + The appended integer + +### `SBc` +Appends a byte, to the active `StringBuilder`. (e.g. 82 for 'R' - An ASCII table can be quickly found) +```dae +func void SBc(var int c) +``` +**Parameters** + +- `#!dae var int c` + The appended byte (ASCII table character) + +### `SBraw` +Appends a raw bytes array, to the active `StringBuilder`. +```dae +func void SBraw(var int ptr, var int len) +``` +**Parameters** + +- `#!dae var int ptr` + Pointer to the appended array +- `#!dae var int len` + Length of an array + +### `SBflt` +Appends a Daedalus float in text form, to the active `StringBuilder`. +```dae +func void SBflt(var float x) +``` +**Parameters** + +- `#!dae var float x` + The appended Daedalus float value + +### `SBf` +Appends an [Ikarus float](../../ikarus/floats.md) in text form, to the active `StringBuilder`. +```dae +func void SBf(var int x) +``` +**Parameters** + +- `#!dae var float x` + The appended Ikarus float value + +### `SBw` +Appends a 4-byte raw data (interpreted as an integer `x`), to the active `StringBuilder`. +```dae +func void SBw(var int x) +``` +**Parameters** + +- `#!dae var int i` + The appended value + +## Independent Functions + +### `STR_Escape` +Makes escape sequences out of non-writable characters. For example, newline character `\n` becomes `\\n`, tab character `\t` becomes `\\t`, etc. +```dae +func string STR_Escape(var string s0) +``` +**Parameters** + +- `#!dae 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. + + +### `STR_Unescape` +Counterpart to `STR_Escape`. Escape sequences like `\n`, `\r` or `\t` are converted back. +```dae +func string STR_Unescape(var string s0) +``` +**Parameters** + +- `#!dae 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. + +### `STR_StartsWith` +Checks if the input string `s` starts with the specified prefix string. +```dae +func int STR_StartsWith(var string str, var string start) +``` +**Parameters** + +- `#!dae var string str` + The string to be checked +- `#!dae var string start` + The searched prefix + +**Return value** + +The function returns `TRUE` if the string starts with the prefix, `FALSE` is returned otherwise. + +## Additional Functions + +### `BuildStringSymbolsArray` +Creates an array of all string symbols found in the parser's string table. +```dae +func int BuildStringSymbolsArray() +``` +**Return value** + +The function returns created array. + +### `GetStringSymbolByAddr` +Retrieves the symbol at the specified address from the string table. +```dae +func int BuildStringSymbolsArray() +``` +**Return value** + +The function returns a parser symbol at the given address. + +## Examples + +### Basic functionality +This is how function that builds a string looks without `StringBuilder`: +```dae +func void PrintMyNumbers(var int x0, var int x1, var int x2) { + var string res; + res = ConcatStrings(IntToString(x0), ", "); + res = ConcatStrings(res, IntToString(x1)); + res = ConcatStrings(res, ", "); + res = ConcatStrings(res, IntToString(x2)); + PrintS(res); +}; +``` +And now the function that uses `StringBulider`: +```dae +func void PrintMyNumbers(var int x0, var int x1, var int x2) { + var int s; s = SB_New(); // Create StringBuilder + SBi(x0); // Append Int + SB (", "); // Append string + SBi(x1); // Append Int + SB (", "); // Append string + SBi(x2); // Append Int + PrintS(SB_ToString()); // Get output as a string + SB_Destroy(); // Destroy StringBuilder +}; +``` +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. + +### Multiple StringBuilders +Simple example. We want to fill two StringBuilders at the same time and then return them combined: +```dae +func string Example2() { + // Create two StringBuilders: + var int s0; s0 = SB_New(); + var int s1; s1 = SB_New(); + + // Set the first StringBuilder as active and fill it. + SB_Use(s0); + SB("Hello "); + SB("World!"); + + // Set the second StringBuilder as active and fill it. + SB_Use(s1); + SB("This is "); + SB("the hero speaking!"); + + // Now we want to combine the two StringBuilders. + // The system doesn't actually provide for such an operation, but it can still be done using a helper string + var string str; str = SB_ToString(); // This string now says “This is the hero speaking!” + + SB_Use(s0); + SB(" "); + SB(str); + + str = SB_ToString(); // Now "Hello world! This is the hero speaking!" are in the string. + + // The rest is already known, we destroy StringBuilders + SB_Destroy(); + SB_Use(s1); + SB_Destroy(); + + return str; +}; +``` \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/tools/talents.md b/docs/zengin/scripts/extenders/lego/tools/talents.md index 9f7921d68c..e252dd067c 100644 --- a/docs/zengin/scripts/extenders/lego/tools/talents.md +++ b/docs/zengin/scripts/extenders/lego/tools/talents.md @@ -1,3 +1,7 @@ +--- +title: Talents +description: LeGo package providing an extension for AIVar array +--- # Talents The Talents package does two things: @@ -8,7 +12,7 @@ Talents package uses one free AIVar variables, the default is AIVar with the ind ## Dependencies -- PermMem +- [PermMem](permmem.md) ## Initialization Initialize with `LeGo_PermMem` flag. @@ -21,11 +25,11 @@ LeGo_Init(LeGo_PermMem); ## Functions -### `NPC_GetID` +### `Npc_GetID` Returns unique ID specific for provided NPC. ```dae -func int NPC_GetID(var C_NPC slf) +func int Npc_GetID(var C_NPC slf) ``` **Parameters** @@ -36,10 +40,10 @@ func int NPC_GetID(var C_NPC slf) The function returns NPCs unique ID. -### `NPC_FindByID` +### `Npc_FindByID` Finds the NPC pointer of an NPC with the given ID. ```dae -func int NPC_FindByID(var int ID) +func int Npc_FindByID(var int ID) ``` **Parameters** @@ -73,7 +77,7 @@ func void TAL_SetValue(var C_NPC npc, var int talent, var int value) - `#!dae var int value` Value to be set -### TAL_GetValue +### `TAL_GetValue` Returns the value of a saved talent for specified NPC. ```dae func int TAL_GetValue(var C_NPC npc, var int talent) diff --git a/docs/zengin/scripts/extenders/lego/tools/talents.pl.md b/docs/zengin/scripts/extenders/lego/tools/talents.pl.md index 50f5ae20a3..e7689a3069 100644 --- a/docs/zengin/scripts/extenders/lego/tools/talents.pl.md +++ b/docs/zengin/scripts/extenders/lego/tools/talents.pl.md @@ -1,5 +1,6 @@ --- -title: Talenty +title: Talents +description: Pakiet LeGo zapewniający rozszerzenie dla tablicy AIVar --- # Talents - talenty Ten pakiet robi dwie rzeczy: @@ -11,7 +12,7 @@ Pakiet `Talents` używa jednego wolnego AIVara, domyślnie jest to AIVar z numer ## Zależności -- PermMem +- [PermMem](permmem.md) ## Inicjalizacja Zainicjuj za pomocą flagi `LeGo_PermMem`. diff --git a/docs/zengin/scripts/extenders/lego/tools/timer.md b/docs/zengin/scripts/extenders/lego/tools/timer.md index 38a8d6ddc7..11bb06fb40 100644 --- a/docs/zengin/scripts/extenders/lego/tools/timer.md +++ b/docs/zengin/scripts/extenders/lego/tools/timer.md @@ -1,3 +1,7 @@ +--- +title: Timer +description: LeGo package for better game timer handling +--- # Timer Timer is a better alternative to the timers that Gothic offers. The [FrameFunctions](frame_functions.md) and [Anim8](../applications/anim8.md) packages are already based on it. It isn't possible to modify the current time, as this would only cause difficulties. diff --git a/docs/zengin/scripts/extenders/lego/tools/view.md b/docs/zengin/scripts/extenders/lego/tools/view.md new file mode 100644 index 0000000000..ada2fc380a --- /dev/null +++ b/docs/zengin/scripts/extenders/lego/tools/view.md @@ -0,0 +1,359 @@ +--- +title: View +description: LeGo package for `zCView` handling in daedalus +--- +# View +This package can create textures on the screen and work with them in an extended manner. + +## Dependencies +- [PermMem](permmem.md) +- [Interface](interface.md) + +## Initialization +Initialize with `LeGo_View` flag. +```dae +LeGo_Init(LeGo_View); +``` + +## Implementation +[:material-github: View.d on GitHub](https://github.com/Lehona/LeGo/blob/dev/View.d) + +## Functions + +### `View_Create` +Creates a `zCView` with virtual coordinates. +```dae +func int View_Create(var int x1, var int y1, var int x2, var int y2) +``` +**Parameters** + +- `#!dae var int x1`/`#!dae var int y1` + Top-left corner coordinates (virtual) +- `#!dae var int x2`/`#!dae var int y2` + Bottom-right corner coordinates (virtual) + +**Return value** + +The function returns a [PermMem](permmem.md) handle to a `zCView`. + +### `View_CreatePxl` +Alias for [`View_Create`](#view_create) using pixel coordinates. +```dae +func int View_CreatePxl(var int x1, var int y1, var int x2, var int y2) +``` +**Parameters** + +- `#!dae var int x1`/`#!dae var int y1` + Top-left corner coordinates (pixel) +- `#!dae var int x2`/`#!dae var int y2` + Bottom-right corner coordinates (pixel) + +**Return value** + +The function returns a [PermMem](permmem.md) handle to a `zCView`. + +### `View_CreateCenter` +Creates a `zCView` with virtual coordinates centered. +```dae +func int View_CreateCenter(var int x, var int y, var int width, var int height) +``` +**Parameters** + +- `#!dae var int x` + Horizontal position +- `#!dae var int y` + Vertical position +- `#!dae var int width` + Width of the view +- `#!dae var int height` + Height of the view + +**Return value** + +The function returns a [PermMem](permmem.md) handle to a `zCView`. + +### `View_CreateCenterPxl` +Alias for `View_CreateCenter` using pixel coordinates. +```dae +func int View_CreateCenterPxl(var int x, var int y, var int width, var int height) +``` +**Parameters** + +- `#!dae var int x` + Horizontal position +- `#!dae var int y` + Vertical position +- `#!dae var int width` + Width of the view +- `#!dae var int height` + Height of the view + +**Return value** + +The function returns a [PermMem](permmem.md) handle to a `zCView`. + +### `View_Get` +Alias for [`get`](permmem.md#get) form [PermMem](permmem.md). +```dae +zCView View_Get(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_GetPtr` +Alias for [`getPtr`](permmem.md#getptr) form [PermMem](permmem.md). +```dae +func int View_GetPtr(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_Render` +Renders a `zCView`. Should be used sparingly, as it works only in specific cases. +```dae +func void View_Render(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_SetTexture` +Assigns a texture to a view. The key function of this package. +```dae +func void View_SetTexture(var int hndl, var string texture) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var string texture` + Filename of a texture + +### `View_GetTexture` +Gets the name of a previously assigned texture. +```dae +func string View_GetTexture(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +**Return value** + +The function returns the previously assigned texture. + +### `View_SetColor` +Sets the color of a view. +```dae +func void View_SetColor(var int hndl, var int color) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int color` + zColor, can be created with RGBA + +### `View_GetColor` +Gets the color of a view. +```dae +func int View_GetColor(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +**Return value** + +The function returns the full zColor. + +### `View_Open` +Opens a view. It will be displayed on the screen. +```dae +func void View_Open(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_Close` +Closes a view. It disappears from the screen but can still be used. +```dae +func void View_Close(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_Delete` +Alias for `delete`. +```dae +`zCView` View_Delete(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_Resize` +Scales a view to a virtual size. The top-left position of the view remains fixed. +```dae +func void View_Resize(var int hndl, var int width, var int height) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int width` + New width of the view +- `#!dae var int height` + New height of the view + +### `View_ResizePxl` +Alias for [`View_Resize`](#view_resize) using pixel coordinates. +```dae +func void View_ResizePxl(var int hndl, var int width, var int height) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int width` + New width of the view +- `#!dae var int height` + New height of the view + +### `View_Move` +Moves the view by virtual units. +```dae +func void View_Move(var int hndl, var int x, var int y) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int x` + Shift left/right +- `#!dae var int y` + Shift up/down + +### `View_MovePxl` +Alias for [`View_Move`](#view_move) using pixel coordinates. +```dae +func void View_MovePxl(var int hndl, var int x, var int y) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int x` + Shift left/right +- `#!dae var int y` + Shift up/down + +### `View_MoveTo` +Moves the top-left corner of the view to a virtual position. +```dae +func void View_MoveTo(var int hndl, var int x, var int y) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int x` + New horizontal position (-1 for no change) +- `#!dae var int y` + New vertical position (-1 for no change) + +### `View_MoveToPxl` +Alias for [`View_MoveTo`](#view_moveto) using pixel coordinates. +```dae +func void View_MoveToPxl(var int hndl, var int x, var int y) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int x` + New horizontal position (-1 for no change) +- `#!dae var int y` + New vertical position (-1 for no change) + +### `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. +```dae +func void View_AddText(var int hndl, var int x, var int y, var string text, var string font) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) +- `#!dae var int x` + Horizontal position +- `#!dae var int y` + Vertical position +- `#!dae var string text` + Added text +- `#!dae var string font` + Used Font + +### `View_DeleteText` +Removes all text added with [`View_AddText`](#view_addtext). +```dae +func void View_DeleteText(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + +### `View_Top` +Places the view above all others. +```dae +func void View_Top(var int hndl) +``` +**Parameters** + +- `#!dae var int hndl` + Handle created with [`View_Create`](#view_get) + + +## Examples + +### Display a texture on the screen +Here a texture should be displayed over the entire screen: +```dae +func void Example1() { + var int View; + View = View_Create(0, 0, PS_VMax, PS_VMax); // Virtual coordinates + View_SetTexture(View, "MyTexture.tga"); // Assign a texture to the view + // display the view on the screen: + View_Open(View); +}; +``` + +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`](#view_delete) or [`View_Close`](#view_close). + +### Display a texture with pixel coordinates +Now a texture should be displayed at the top right and be 256 x 256 pixels in size: +```dae +func void Example2() { + Print_GetScreenSize(); + var int View; + View = View_CreatePxl(Print_Screen[PS_X] - 256, 0, Print_Screen[PS_X], 256); // Pixel coordinates + View_SetTexture(View, "MYTEXTURE.TGA"); + View_Open(View); +}; +``` + +To get the size of the screen we use the [interface](interface.md) package. \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/lego/various/userconstants.md b/docs/zengin/scripts/extenders/lego/various/userconstants.md index c1be06fb4f..1bb6628585 100644 --- a/docs/zengin/scripts/extenders/lego/various/userconstants.md +++ b/docs/zengin/scripts/extenders/lego/various/userconstants.md @@ -1,3 +1,7 @@ +--- +title: User constants +description: LeGo package user-configurable constants description +--- # User constants All constants that the user can either use or even change freely are defined in [Userconst.d](https://github.com/Lehona/LeGo/blob/dev/Userconst.d) file. diff --git a/docs/zengin/scripts/extenders/standalone/gameKeyEvents.md b/docs/zengin/scripts/extenders/standalone/gameKeyEvents.md new file mode 100644 index 0000000000..45a5f9faab --- /dev/null +++ b/docs/zengin/scripts/extenders/standalone/gameKeyEvents.md @@ -0,0 +1,44 @@ +# gameKeyEvents + +!!! Abstract inline end "Quick overview" + **Author:** [mud-freak](https://forum.worldofplayers.de/forum/members/25960-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`](../lego/tools/frame_functions.md) with [`MEM_KeyState`](../ikarus/functions/keyboard.md#mem_keystate) with which you don't have to check whether any menu is opened or player is in dialogue or can move etc. + +??? trivia "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. + +## Dependencies +- [Ikarus](../ikarus/index.md) +- [HookEngine](../lego/tools/hook_engine.md) + +## Initialization +Call `Game_KeyEventInit()` in the `Init_Global()` or other initialization function. +```dae +Game_KeyEventInit(); +``` + +## Implementation +[:material-forum: gameKeyEvents.d on WoG forum](https://forum.worldofplayers.de/forum/threads/1495001-Scriptsammlung-ScriptBin/page4?p=26055992&viewfull=1#post26055992) + +## Usage +To add a key pressing detection edit the main function `Game_KeyEvent`. +```dae +func int Game_KeyEvent(var int key, var int pressed) { + if (key == KEY_LBRACKET) && (pressed) { + // Here enter your code. + return TRUE; + }; + return FALSE; +}; +``` + +- To change detected key rename `KEY_LBRACKET` to your own key e.g. taken from [Ikarus constants](https://github.com/Lehona/Ikarus/blob/master/Ikarus_Const_G2.d#L129-L288). +- To detect pressing a key leave `(pressed)` unchanged but if you want to detect holding change it to `(!pressed)`. That's because +> pressed is FALSE: key is held, pressed is TRUE: key press onset +- To run code when a key is pressed, paste it or call a function where the comment is. +- To detect more than one key add `else if`. diff --git a/docs/zengin/scripts/extenders/standalone/index.md b/docs/zengin/scripts/extenders/standalone/index.md new file mode 100644 index 0000000000..427b587521 --- /dev/null +++ b/docs/zengin/scripts/extenders/standalone/index.md @@ -0,0 +1,18 @@ +# Standalone Scripts +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. + +## Script Bins +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](https://forum.worldofplayers.de/forum/threads/1495001-Scriptsammlung-ScriptBin). + +### WoG Script Bin +Script bin made by Kirides containing scripts from German WoG forum. + +[https://apps.kirides.de/wog-script-bin/](https://apps.kirides.de/wog-script-bin/) + +### ScriptBin GitHub repository +Lehona has created a GitHub repository that contains scripts from some of the modders. + +[https://github.com/Lehona/ScriptBin](https://github.com/Lehona/ScriptBin) \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/standalone/index.pl.md b/docs/zengin/scripts/extenders/standalone/index.pl.md new file mode 100644 index 0000000000..78092a5804 --- /dev/null +++ b/docs/zengin/scripts/extenders/standalone/index.pl.md @@ -0,0 +1,18 @@ +# Samodzielne skrypty +Przez lata moderzy Gothica stworzyli wiele przydatnych funkcji do wykorzystania ze skryptami Zengin. Ta sekcja zawiera dokumentację niektórych skryptów, które są „samodzielne”, co oznacza, że nie są częścią większych pakietów, ale często są to małe funkcje ułatwiające życie modderom. + +## Script Biny +Kilka osób wpadło na pomysł zebrania rozsianych po forach skryptów, w wyniku czego powstały tzw. Script Biny. + +!!! Warning + Script biny nie są często aktualizowane, więc najnowsze aktualizacje i nowe skrypty można znaleźć w [wątku ScriptBin](https://forum.worldofplayers.de/forum/threads/1495001-Scriptsammlung-ScriptBin) na niemieckim forum WoG. + +### WoG Script Bin +Script bin stworzony przez Kiridesa zawierający skrypty z niemieckiego forum WoG. + +[https://apps.kirides.de/wog-script-bin/](https://apps.kirides.de/wog-script-bin/) + +### Repozytorium ScriptBin na GitHubie +Repozytorium GitHub stworzone przez Lehone, które zawiera skrypty niektórych modderów. + +[https://github.com/Lehona/ScriptBin](https://github.com/Lehona/ScriptBin) \ No newline at end of file diff --git a/docs/zengin/scripts/extenders/standalone/setBarPositions.md b/docs/zengin/scripts/extenders/standalone/setBarPositions.md new file mode 100644 index 0000000000..ce89371e70 --- /dev/null +++ b/docs/zengin/scripts/extenders/standalone/setBarPositions.md @@ -0,0 +1,88 @@ +# setBarPositions + +!!! Abstract inline end "Quick overview" + **Author:** [mud-freak](https://forum.worldofplayers.de/forum/members/25960-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. + +## Dependencies +- [Ikarus](../ikarus/index.md) +- [HookEngine](../lego/tools/hook_engine.md) + +## Initialization +Call it in the `Init_Global()` or other initialization function. Set the `manaAlwaysOn` and `swimAlwaysOn` to TRUE/FALSE. +```dae +SetBarPositions_Init(manaAlwaysOn, swimAlwaysOn); +``` + +## Implementation +[:material-forum: setBarPositions.d on WoG forum](https://forum.worldofplayers.de/forum/threads/?p=26426112) + +## Usage +To change positions of bars edit the main function `SetBarPosition`. Look at the examples to see how you can adjust it to your preferences. +```dae +func int SetBarPosition(var int barPtr) { + var oCViewStatusBar bar; bar = _^(barPtr); + var int x; var int y; + + if (barPtr == MEM_Game.hpBar) { + // Original + x = Print_ToVirtual(10, PS_X); // 10 px from the left + y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom + + } else if (barPtr == MEM_Game.manaBar) { + // Original + x = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizex, PS_X); // 10 px from the right + y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom + + } else if (barPtr == MEM_Game.swimBar) { + // Original + x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered + y = PS_VMax - Print_ToVirtual(10 + bar.zCView_psizey, PS_Y); // 10 px from the bottom + + } else if (barPtr == MEM_Game.focusBar) { + // Original + x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered + y = Print_ToVirtual(10, PS_Y); // 10 px from the top + }; + + return x | (y << 14); +}; +``` + +## Examples + +### All bars on the left side +```dae + + +/* + * EXAMPLE: Stacked on the left + */ +func int SetBarPosition(var int barPtr) { + var oCViewStatusBar bar; bar = _^(barPtr); + var int x; var int y; + + if (barPtr == MEM_Game.hpBar) { + x = Print_ToVirtual(10, PS_X); + y = PS_VMax - Print_ToVirtual(6 + 3 * (4 + bar.zCView_psizey), PS_Y); + + } else if (barPtr == MEM_Game.manaBar) { + x = Print_ToVirtual(10, PS_X); + y = PS_VMax - Print_ToVirtual(6 + 2 * (4 + bar.zCView_psizey), PS_Y); + + } else if (barPtr == MEM_Game.swimBar) { + x = Print_ToVirtual(10, PS_X); + y = PS_VMax - Print_ToVirtual(6 + 1 * (4 + bar.zCView_psizey), PS_Y); + + } else if (barPtr == MEM_Game.focusBar) { + // Original + x = (PS_VMax - bar.zCView_vsizex) / 2; // Centered + y = Print_ToVirtual(10, PS_Y); // 10 px from the top + }; + + return x | (y << 14); +}; +``` diff --git a/docs/zengin/scripts/extenders/zparserextender/classes/c_trigger.md b/docs/zengin/scripts/extenders/zparserextender/classes/c_trigger.md index ba3ab90bf6..a07eda08ef 100644 --- a/docs/zengin/scripts/extenders/zparserextender/classes/c_trigger.md +++ b/docs/zengin/scripts/extenders/zparserextender/classes/c_trigger.md @@ -8,10 +8,10 @@ zParserExtender also implements cyclical functions called triggers - not to be c To define a trigger, the `C_Trigger` class is used: ```dae -/// Union zPraserExtender Trigger class +/// Union zParserExtender Trigger class class C_Trigger { - var int Delay; // defines the frequency (in miliseconds) at which the function will be called. + var int Delay; // defines the frequency (in milliseconds) at which the function will be called. var int Enabled; // determines if the trigger is active. If the value is equal to zero, the trigger is destroyed. var int AIVariables[16]; // user data, which can be set independently when creating trigger (yes, you can write there absolutely everything you want). @@ -93,12 +93,12 @@ To search for a specific trigger, for example by NPC, the [trigger external func ```dae // This way you can disable all triggers running on the `hero` instance -var C_Trigger trigget = FirstTrigger; -var C_Trigger trigget_saved; -while (!Hlp_IsNULL(trigget)) +var C_Trigger trigger = FirstTrigger; +var C_Trigger trigger_saved; +while (!Hlp_IsNULL(trigger)) { - trigget_saved = trigger; + trigger_saved = trigger; trigger = AI_GetNextTriggerBySelf(hero); - trigget_saved.Enabled = false; + trigger_saved.Enabled = false; }; ``` diff --git a/docs/zengin/scripts/extenders/zparserextender/classes/helperclasses.md b/docs/zengin/scripts/extenders/zparserextender/classes/helperclasses.md index f0e7427039..513a39cc47 100644 --- a/docs/zengin/scripts/extenders/zparserextender/classes/helperclasses.md +++ b/docs/zengin/scripts/extenders/zparserextender/classes/helperclasses.md @@ -18,6 +18,17 @@ class C_Color }; ``` +## zVEC3 +Represents 3D position in the world (float version for internal functions) +```dae +class zVEC3 +{ + var float X; // X coordinate + var float Y; // Y coordinate + var float Z; // Z coordinate +}; +``` + ## C_Position Represents 3D position in the world ```dae @@ -33,7 +44,7 @@ Externals: /// Returns the current position of the object in the world /// /// @param vob vob to ge the position of -/// @return C_Position instace - position of the VOB +/// @return C_Position instance - position of the VOB func C_Position Vob_GetVobPosition( var C_Vob vob ) {}; /// Sets the current position of the object in the world @@ -47,7 +58,7 @@ func void Vob_SetVobPosition( var C_Vob vob, var C_Position pos ) {}; The following classes define properties of `C_VOB` objects or classes derived from it. ## C_VOB_DATA -Represents universal `zCVob` class +Represents universal [`zCVob`](../../../../worlds/Classes/zCVob.md) class ```dae class C_VOB_DATA { @@ -61,8 +72,8 @@ class C_VOB_DATA var int CollDetectionStatic; // allow collision with static world polygons var int CollDetectionDynamic; // allow collision with dynamic world objects var int CastDynShadow; // display shadow of the object - var int LightColorStatDirty; // allow static liging of the object - var int LightColorDynDirty; // allow dynamic lighing of the object + var int LightColorStatDirty; // allow static lighting of the object + var int LightColorDynDirty; // allow dynamic lighting of the object var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only) var int DontWriteIntoArchive; // turns of the serialization of this object to the save file }; diff --git a/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/meta.md b/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/meta.md index 2abe4d6de7..84ab058708 100644 --- a/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/meta.md +++ b/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/meta.md @@ -17,7 +17,7 @@ META Menu parserMenu Menu.dat Music parserMusic Music.dat */ - MergeMode // 0 - if confilct occurs = comilation error, 1 - if conflict occurs = hook + MergeMode // 0 - if conflict occurs = compilation error, 1 - if conflict occurs = hook Engine // comma separated list of engines for which the scripts will be injected /* Code Engine Human readable name diff --git a/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/other.md b/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/other.md index 05d05ab525..08574b9b2c 100644 --- a/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/other.md +++ b/docs/zengin/scripts/extenders/zparserextender/daedalus_injection/other.md @@ -37,7 +37,7 @@ StringIndexingMode = -1 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 whe using the command. + 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 diff --git a/docs/zengin/scripts/extenders/zparserextender/examples/signposts.md b/docs/zengin/scripts/extenders/zparserextender/examples/signposts.md index fc3e2804e2..7b052bf967 100644 --- a/docs/zengin/scripts/extenders/zparserextender/examples/signposts.md +++ b/docs/zengin/scripts/extenders/zparserextender/examples/signposts.md @@ -9,7 +9,7 @@ The goal is to introduce a function that will teleport you to every signpost in 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. ## ASCII ZEN -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](https://dziejekhorinis.org/dev/vobbilder/). +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](https://vobbilder.dziejekhorinis.org/vobbilder/). 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. ```ini title="One signpost object" hl_lines="6 8" @@ -59,7 +59,7 @@ Next, the world was saved as a `ASCII ZEN` format. This allows us to write a mac ## The injectable script As it is an injectable script, we have to specify the `META` tag. -Lets tell zParseExtender to insert this code into the game parser. +Lets tell zParserExtender to insert this code into the game parser. ```dae META { @@ -87,8 +87,8 @@ class C_VOB_DATA var int CollDetectionStatic; // allow collision with static world polygons var int CollDetectionDynamic; // allow collision with dynamic world objects var int CastDynShadow; // display shadow of the object - var int LightColorStatDirty; // allow static liging of the object - var int LightColorDynDirty; // allow dynamic lighing of the object + var int LightColorStatDirty; // allow static lighting of the object + var int LightColorDynDirty; // allow dynamic lighting of the object var int SleepingMode; // sets object's activity mode (0 - inactive, 1 - active, 2 - AI only) var int DontWriteIntoArchive; // turns of the serialization of this object to the save file }; diff --git a/docs/zengin/scripts/extenders/zparserextender/externals/events_vars.md b/docs/zengin/scripts/extenders/zparserextender/externals/events_vars.md index e035b7fc98..32d6a718cd 100644 --- a/docs/zengin/scripts/extenders/zparserextender/externals/events_vars.md +++ b/docs/zengin/scripts/extenders/zparserextender/externals/events_vars.md @@ -5,10 +5,10 @@ title: Event functions On top of external functions, zParserExtender also adds these event functions and constants. ```dae -/// Every event function with this name is exectued once every frame +/// Every event function with this name is executed once every frame func event GameLoop() {}; -/// Every event function with this name is exectued once on game init +/// Every event function with this name is executed once on game init func event GameInit() {}; /// empty instance diff --git a/docs/zengin/scripts/extenders/zparserextender/externals/wld.md b/docs/zengin/scripts/extenders/zparserextender/externals/wld.md index 28c2b0c77c..7c4f383008 100644 --- a/docs/zengin/scripts/extenders/zparserextender/externals/wld.md +++ b/docs/zengin/scripts/extenders/zparserextender/externals/wld.md @@ -23,7 +23,6 @@ func instance Wld_FindVob( var string vobname ) {}; - `vobname` - name of the vob - `return` - zCVob pointer -- `return` - ## Wld_PlayEffectVob Play a visual effect at specified vob @@ -38,7 +37,7 @@ func void Wld_PlayEffectVob( var string effect, ``` - `effect` - effect name -- `pvob` - Vob to play the effect at +- `pvob` - zCVob to play the effect at - `level` - effect level - `damage` - damage amount - `damage_type` - damage type @@ -57,7 +56,7 @@ func void Wld_PlayEffectAt( var string effect, ``` - `effect` - effect name -- `coord` - world coordinates to play the effect at +- `coord` - world coordinates (`zVEC3`) to play the effect at - `level` - effect level - `damage` - damage amount - `damage_type` - damage type @@ -86,7 +85,7 @@ func void Wld_SetWeatherType( var int type ) {}; - `type` - weather type -## Wld_GetWeatherType() +## Wld_GetWeatherType Returns the weather type. Types: diff --git a/docs/zengin/scripts/extenders/zparserextender/index.md b/docs/zengin/scripts/extenders/zparserextender/index.md index a57b0b0adb..ebe4ad3a91 100644 --- a/docs/zengin/scripts/extenders/zparserextender/index.md +++ b/docs/zengin/scripts/extenders/zparserextender/index.md @@ -1,5 +1,5 @@ # zParserExtender -zParserExtender extends ZenGins 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. +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](https://worldofplayers.ru/threads/41999/) diff --git a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse.md b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse.md index 8f45c5fabe..5d2b45bf46 100644 --- a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse.md +++ b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/testelse.md @@ -11,7 +11,7 @@ Valid values: - engine tag - `G1`, `G1A`, `G2`, `G2A` - Steam Overlay activity - `Steam` -The result can be combined from several arguments. Round brackets `()` ca be used to specify priority and expressions support the logical negation operator `!`, logical AND `&&` and OR `||`. +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: diff --git a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.md b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.md index 0dd891dc07..447bcd0cba 100644 --- a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.md +++ b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.md @@ -2,7 +2,7 @@ title: While loop --- # Native WHILE loop -Just like [Ikarus](../../../../../notready.md) zParserExtender implements a while loop. +Just like [Ikarus](../../ikarus/functions/jumps_loops.md#while-loop) zParserExtender implements a while loop. ```dae var int value; value = 10; diff --git a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.pl.md b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.pl.md index 1bea568840..1a37665b11 100644 --- a/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.pl.md +++ b/docs/zengin/scripts/extenders/zparserextender/syntax_extensions/while.pl.md @@ -2,7 +2,7 @@ title: Pętla while --- # Natywna pętla WHILE -Podobnie jak [Ikarus](../../../../../notready.md) zParserExtender implementuje pętlę while. +Podobnie jak [Ikarus](../../ikarus/functions/jumps_loops.md#while-loop) zParserExtender implementuje pętlę while. ```dae var int value; value = 10; diff --git a/docs/zengin/scripts/externals/doc.md b/docs/zengin/scripts/externals/doc.md new file mode 100644 index 0000000000..9cf648f0dd --- /dev/null +++ b/docs/zengin/scripts/externals/doc.md @@ -0,0 +1,335 @@ +--- +title: Doc functions +--- +# Doc external functions + +Doc functions are used to control the document manager. They allow you to fine tune the display of maps, letters and books. + +## `Doc_Create` + +Creates a new instance of the document manager and returns its ID. +```dae +func int Doc_Create() {}; +``` + +**Return value** +Returns the ID of the document manager instance. + +!!! Example + ```dae + var int nDocID; // Variable to store the id in + nDocID = Doc_Create(); + ``` + +## `Doc_CreateMap` + +Creates a new instance of the document manager with the arrow showing players position on the map and returns its ID. +```dae +func int Doc_CreateMap() {}; +``` + +**Return value** +Returns the ID of the document manager instance. + +!!! Example + ```dae + var int nDocID; // Variable to store the id in + nDocID = Doc_CreateMap(); + ``` + +## `Doc_SetLevel` + +Set a world level to a map. This maps the texture of the document to the bounding box of the provided level. +```dae +func void Doc_SetLevel(var int docID, var string level) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var string level` - name of the ZEN file + +!!! Example + ```dae + nDocID = Doc_CreateMap(); + Doc_SetLevel(nDocID, "WORLD.ZEN"); + ``` + +## `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. +```dae +func void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int left` - left coordinate +- `#!dae var int top` - top coordinate +- `#!dae var int right` - right coordinate +- `#!dae var int bottom` - bottom coordinate + +!!! Example + ```dae + Doc_SetLevelCoords(nDocID, -28000, 50500, 95500, -42500); + ``` + +## `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. + +```dae +func void Doc_SetFont(var int docID, var int page, var string font) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int page` - page index, if set to `-1`, fonts will be applied to all pages +- `#!dae var string font` - font to be used + +!!! Example + ```dae + Doc_SetFont(nDocID, -1, "FONT_10_BOOK.TGA"); + ``` + +## `Doc_SetPages` + +Sets the number of pages `numOfPages` of the document. +```dae +func void Doc_SetPages(var int docID, var int numOfPages) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int numOfPages` - number of pages + +!!! Example + ```dae + nDocID = Doc_Create(); + Doc_SetPages(nDocID, 2); + ``` + +## `Doc_SetPage` + +Set `page` to have `texture` as a background with `scale`. +```dae +func void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int page` - page index, if set to `-1`, settings are applied to all pages +- `#!dae var string texture` - texture of the background +- `#!dae var int scale` - scale of the texture, `TRUE` to scale the page, `FALSE` to not scale + +!!! Example + ```dae + Doc_SetPage(nDocID, 0, "Book_Mage_L.tga", FALSE); + Doc_SetPage(nDocID, 1, "Book_Mage_R.tga", FALSE); + ``` + +## `Doc_SetMargins` + +Sets text margins of the page +```dae +func void Doc_SetMargins(var int docID, + var int page, + var int left, + var int top, + var int right, + var int bottom, + var int pixels) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int page` - page index, if set to `-1`, settings are applied to all pages +- `#!dae var int left` - left margin +- `#!dae var int top` - top margin +- `#!dae var int right` - right margin +- `#!dae var int bottom` - bottom margin +- `#!dae 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 + ```dae + Doc_SetMargins(nDocID, 0, 275, 20, 30, 20, TRUE); + ``` + +## `Doc_PrintLine` + +Prints a line of `text` (font is set using [Doc_SetFont](#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. +```dae +func void Doc_PrintLine(var int docID, var int page, var string text) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int page` - page index +- `#!dae var string text` - text to be printed + +!!! Example + ```dae + Doc_PrintLine(nDocID, 0, ""); // insert empty line + Doc_PrintLine(nDocID, 0, "The Book"); + ``` + +## `Doc_PrintLines` + +Prints a line of `text` (font is set using [Doc_SetFont](#doc_setfont)) onto the document with `docID`, onto the `page`. Splits the text into multiple lines if they do not fit onto the page. +```dae +func void Doc_PrintLines(var int docID, var int page, var string text) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID +- `#!dae var int page` - page index +- `#!dae var string text` - text to be printed + +!!! Example + ```dae + 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."); + Doc_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."); + ``` + +## `Doc_Show` + +Display the document using the document manager ID +```dae +func void Doc_Show(var int docID) {}; +``` + +**Parameters** + +- `#!dae var int docID` - document manager ID + +!!! Example + ```dae + var int nDocID; // Variable to store the id in + nDocID = Doc_Create(); + + // ... document configuration + + Doc_Show(nDocID); + ``` + +## Externals with docu comments + +```dae +/// Creates a new instance of the document manager and returns its ID. +/// +/// @return Returns the ID of the document manager instance. +func int Doc_Create() {}; + +/// Create a new instance of the document manager with the arrow showing players position on the map and returns its ID. +/// +/// @return Returns the ID of the document manager instance. +func int Doc_CreateMap() {}; + +/// Prints a line of `text` onto the document with `docID`, onto the `page`. +/// Does not line break +/// +/// @param docID document manager ID +/// @param page page index +/// @param text text to be printed +func void Doc_PrintLine(var int docID, var int page, var string text) {}; + +/// Prints a line of `text` onto the document with `docID`, onto the `page`. The `text` is automatically split into multiple lines +/// +/// @param docID document manager ID +/// @param page page index +/// @param text text to be printed +func void Doc_PrintLines(var int docID, var int page, var string text) {}; + +/// 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. +/// +/// @param docID document manager ID +/// @param page page index +/// @param font font to be used +func void Doc_SetFont(var int docID, var int page, var string font) {}; + +/// Sets the number of pages `numOfPages` of the document. +/// +/// @param docID document manager ID +/// @param numOfPages number of pages +func void Doc_SetPages(var int docID, var int numOfPages) {}; + +/// Set `page` to have `texture` as a background with `scale`. +/// +/// @param docID document manager ID +/// @param page page index, if set to `-1`, settings are applied to all pages +/// @param texture texture of the background +/// @param scale scale of the texture, if set to 1, there will be no resizing +func void Doc_SetPage(var int docID, var int page, var string texture, var int scale) {}; + +/// Set a world level to a map. +/// +/// @param docID document manager ID +/// @param level name of the ZEN file +func void Doc_SetLevel(var int docID, var string level) {}; + +/// Sets the map coordinates. +/// +/// @param docID document manager ID +/// @param left left +/// @param top top +/// @param right top +/// @param bottom bottom +func void Doc_SetLevelCoords(var int docID, var int left, var int top, var int right, var int bottom) {}; + +/// Sets text margins of the page +/// +/// @param docID document manager ID +/// @param page page index, if set to `-1`, settings are applied to all pages +/// @param left left margin +/// @param top top margin +/// @param right right margin +/// @param bottom bottom margin +/// @param pixels `TRUE` to use pixels, `FALSE` to use virtual coordinates +func void Doc_SetMargins(var int docID, + var int page, + var int left, + var int top, + var int right, + var int bottom, + var int pixels) {}; + +/// Display the document using the document manager ID +/// +/// @param docID document manager ID +func void Doc_Show(var int docID) {}; + + + +/// deprecated +func void Doc_Open (var string Texture) {}; + +/// deprecated +func void Doc_Font(var string Font) {}; + +/// deprecated +func void Doc_Print (var string Text) {}; + +/// deprecated +func void Doc_MapCoordinates(var string s0, + var float r1, + var float r2, + var float r3, + var float r4, + var float r5, + var float r6, + var float r7, + var float r8) {}; +``` + + diff --git a/docs/zengin/scripts/externals/externals.d b/docs/zengin/scripts/externals/externals.d new file mode 100644 index 0000000000..6750beba60 --- /dev/null +++ b/docs/zengin/scripts/externals/externals.d @@ -0,0 +1,353 @@ +func void AI_AimAt(var c_npc attacker, var c_npc target) {}; +func void AI_AlignToFP(var c_npc self) {}; +func void AI_AlignToWP(var c_npc self) {}; +func void AI_AskText(var c_npc self, var func funcyes, var func funcno, var string stryes, var string strno) {}; +func void AI_Ask(var c_npc self, var func anseryes, var func answerno) {}; +func void AI_Attack(var c_npc self) {}; +func void AI_CanSeeNpc(var instance n0, var instance n1, var func f2) {}; +func void AI_CombatReactToDamage(var instance n0) {}; +func void AI_ContinueRoutine(var c_npc self) {}; +func void AI_Defend(var c_npc self) {}; +func void AI_Dodge(var c_npc npc) {}; +func void AI_DrawWeapon(var c_npc n0) {}; +func void AI_DropItem(var c_npc self, var int itemid) {}; +func void AI_DropMob(var instance n0) {}; +func void AI_EquipArmor(var c_npc owner, var c_item armor_from_owners_inventory) {}; +func void AI_EquipBestArmor(var c_npc self) {}; +func void AI_EquipBestMeleeWeapon(var c_npc self) {}; +func void AI_EquipBestRangedWeapon(var c_npc self) {}; +func void AI_FinishingMove(var c_npc self, var c_npc other) {}; +func void AI_Flee(var c_npc self) {}; +func void AI_GotoFP(var c_npc self, var string fpname) {}; +func void AI_GotoItem(var c_npc self, var c_item item) {}; +func void AI_GotoNextFP(var c_npc self, var string fpname) {}; +func void AI_GotoNpc(var c_npc self, var c_npc other) {}; +func void AI_GotoSound(var c_npc n0) {}; +func void AI_GotoWP(var c_npc n0, var string s0) {}; +func void AI_LookAtNpc(var c_npc self, var c_npc other) {}; +func void AI_LookAt(var c_npc self, var string name) {}; +func void AI_LookForItem(var c_npc self, var int instance) {}; +func void AI_OutputSVM_Overlay(var c_npc self, var c_npc target, var string svmname) {}; +func void AI_OutputSVM(var c_npc self, var c_npc target, var string svmname) {}; +func void AI_Output(var c_npc self, var c_npc target, var string outputname) {}; +func void AI_PlayAniBS(var c_npc npc, var string aniname, var int bodystate) {}; +func void AI_PlayAni(var c_npc n0, var string s0) {}; +func void AI_PlayCutscene(var c_npc self, var string csname) {}; +func void AI_PlayFX(var instance n0, var instance n1, var string s2) {}; +func void AI_PointAtNpc(var c_npc self, var c_npc other) {}; +func void AI_PointAt(var c_npc self, var string name) {}; +func int AI_PrintScreen(var string s0, var int i1, var int i2, var string s3, var int i4) {}; +func void AI_ProcessInfos(var instance n0) {}; +func void AI_Quicklook(var c_npc self, var c_npc other) {}; +func void AI_QuickLook(var instance n0, var instance n1) {}; +func void AI_ReadyMeleeWeapon(var c_npc self) {}; +func void AI_ReadyRangedWeapon(var c_npc self) {}; +func void AI_ReadySpell(var c_npc self, var int spellid, var int investmana) {}; +func void AI_RemoveWeapon(var c_npc n0) {}; +func void AI_SetNpcsToState(var c_npc self, var func aistatefunc, var int radius) {}; +func void AI_SetWalkmode(var c_npc n, var int n0) {}; +func void AI_SetWalkMode(var instance n0, var int i1) {}; +func void AI_ShootAt(var c_npc attacker, var c_npc target) {}; +func void AI_Snd_Play(var instance n0, var string s1) {}; +func void AI_Snd_Play3D(var instance n0, var instance n1, var string s2) {}; +func void AI_StandUpQuick(var c_npc self) {}; +func void AI_StandUp(var c_npc self) {}; +func void AI_StartState(var c_npc self, var func what, var int statebehaviour, var string wpname) {}; +func void AI_StopAim(var c_npc attacker) {}; +func void AI_StopFX(var instance n0, var string s1) {}; +func void AI_StopLookAt(var c_npc self) {}; +func void AI_StopPointAt(var c_npc self) {}; +func void AI_StopProcessInfos(var c_npc npc) {}; +func void AI_TakeItem(var c_npc self, var c_item item) {}; +func void AI_TakeMob(var instance n0, var string s1) {}; +func void AI_Teleport(var c_npc self, var string waypoint) {}; +func void AI_TurnAway(var c_npc n0, var c_npc n1) {}; +func void AI_TurnToNpc(var c_npc n0, var c_npc n1) {}; +func void AI_TurnToSound(var c_npc self) {}; +func void AI_UnequipArmor(var c_npc self) {}; +func void AI_UnequipWeapons(var c_npc self) {}; +func void AI_UnreadySpell(var c_npc self) {}; +func void AI_UseItemToState(var c_npc self, var int iteminstance, var int state) {}; +func void AI_UseItem(var c_npc self, var int iteminstance) {}; +func int AI_UseMob(var c_npc self, var string schemename, var int targetstate) {}; +func void AI_WaitForQuestion(var c_npc self, var func scriptfunc) {}; +func void AI_WaitMS(var instance n0, var int i1) {}; +func void AI_WaitTillEnd(var c_npc self, var c_npc other) {}; +func void AI_Wait(var c_npc n0, var float n1) {}; +func void AI_WhirlAroundToSource(var instance n0) {}; +func void AI_WhirlAround(var c_npc self, var c_npc other) {}; +func void Apply_Options_Audio() {}; +func void Apply_Options_Controls() {}; +func void Apply_Options_Game() {}; +func void Apply_Options_Performance() {}; +func void Apply_Options_Video() {}; +func string ConcatStrings(var string str1, var string str2) {}; +func void CreateInvItems(var c_npc n0, var int n1, var int n2) {}; +func void CreateInvItem(var c_npc n0, var int n1) {}; + +func int Doc_Create() {}; +func int Doc_CreateMap() {}; +func void Doc_Font (var string Font) {}; +func void Doc_Font(var string s0) {}; +func void Doc_MapCoordinates (var string Level, var float GameX1, var float GameY1, var float PixelX1, var float PixelY1, var float GameX2, var float GameY2, var float PixelX2, var float PixelY2) {}; +func void Doc_MapCoordinates(var string s0, var float r1, var float r2, var float r3, var float r4, var float r5, var float r6, var float r7, var float r8) {}; +func void Doc_Open(var string s0) {}; +func void Doc_Open (var string Texture) {}; +func void Doc_PrintLines(var int document, var int page, var string text) {}; +func void Doc_PrintLine(var int document, var int page, var string text) {}; +func void Doc_Print(var string s0) {}; +func void Doc_Print (var string Text) {}; +func void Doc_SetFont(var int document, var int page, var string font) {}; +func void Doc_SetLevelCoords(var int document, var int left, var int top, var int right, var int bottom) {}; +func void Doc_SetLevel(var int document, var string level) {}; +func void Doc_SetMargins(var int document, var int page, var int left, var int top, var int right, var int bottom, var int pixels) {}; +func void Doc_SetPages(var int document, var int count) {}; +func void Doc_SetPage(var int document, var int page, var string texture, var int scale) {}; +func void Doc_Show(var int document) {}; + +func void EquipItem(var c_npc n0, var int n1) {}; +func void ExitGame() {}; +func void ExitSession() {}; +func int FloatToInt(var float x) {}; +func string FloatToString(var float r0) {}; +func void Game_InitEnglish() {}; +func void Game_InitGerman() {}; +func int Hlp_CutscenePlayed(var string csname) {}; +func int Hlp_GetInstanceID(var c_item item) {}; +func c_npc Hlp_GetNpc(var int instancename) {}; +func int Hlp_IsItem(var c_item item, var int instancename) {}; +func int Hlp_IsValidItem(var c_item item) {}; +func int Hlp_IsValidNpc(var c_npc self) {}; +func int Hlp_Random(var int n0) {}; +func int Hlp_StrCmp(var string s1, var string s2) {}; +func void Info_AddChoice(var int i0, var string s1, var func f2) {}; +func void Info_ClearChoices(var int i0) {}; +func int InfoManager_HasFinished() {}; +func void IntroduceChapter(var string titel, var string untertitel, var string texture, var string sound, var int waittime) {}; +func float IntToFloat(var int x) {}; +func string IntToString(var int x) {}; + +/// Creates a new log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in +func void Log_CreateTopic(var string topicName, var int logSection) {}; +/// Adds an entry to a log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param entry content of the new entry +func void Log_AddEntry(var string topicName, var string entry) {}; +/// Changes the status of the topic with the name `topicName` +/// +/// @param topicName unique string used to identify and name the topic +/// @param status [LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE] the status to be set +func void Log_SetTopicStatus(var string TopicName, var int status) {}; + +func void Mdl_ApplyOverlayMDSTimed(var c_npc self, var string overlayname, var float timeticks) {}; +func void Mdl_ApplyOverlayMdsTimed(var instance n0, var string s1, var int i2) {}; +func void Mdl_ApplyOverlayMds(var c_npc n0, var string s1) {}; +func void Mdl_ApplyOverlayMDS(var instance n0, var string s1) {}; +func void Mdl_ApplyRandomAniFreq(var c_npc n0, var string s1, var float f2) {}; +func void Mdl_ApplyRandomAni(var c_npc n0, var string s1, var string s2) {}; +func void Mdl_ApplyRandomFaceAni(var c_npc self, var string name, var float timemin, var float timeminvar, var float timemax, var float timemaxvar, var float probmin) {}; +func void Mdl_RemoveOverlayMDS(var c_npc self, var string overlayname) {}; +func void Mdl_SetModelFatness(var c_npc self, var float fatness) {}; +func void Mdl_SetModelScale(var c_npc self, var float x, var float y, var float z) {}; +func void Mdl_SetVisualBody(var instance n0, var string s1, var int i2, var int i3, var string s4, var int i5, var int i6, var int i7) {}; +func void Mdl_SetVisual(var instance n0, var string s1) {}; +func void Mdl_StartFaceAni(var c_npc self, var string name, var float intensity, var float holdtime) {}; + +func void Mis_AddMissionEntry(var instance n0, var string s1) {}; +func int Mis_GetStatus(var int missionname) {}; +func int Mis_OnTime(var int missionname) {}; +func void Mis_RemoveMission(var instance n0) {}; +func void Mis_SetStatus(var int missionname, var int newstatus) {}; +func void Mob_CreateItems(var string mobname, var int iteminstance, var int amount) {}; +func int Mob_HasItems(var string mobname, var int iteminstance) {}; +func int Npc_AreWeStronger(var c_npc self, var c_npc other) {}; +func int Npc_CanSeeItem(var c_npc npc1, var c_item item) {}; +func int Npc_CanSeeNpcFreeLOS(var c_npc self, var c_npc other) {}; +func int Npc_CanSeeNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_CanSeeSource(var c_npc self) {}; +func void Npc_ClearAIQueue(var c_npc self) {}; +func void Npc_ClearInventory(var instance n0) {}; +func void Npc_CreateSpell(var c_npc self, var int spellnr) {}; +func int Npc_DeleteNews(var instance n0, var int i1) {}; +func void Npc_ExchangeRoutine(var c_npc self, var string routinename) {}; +func int Npc_GetActiveSpellCat(var c_npc self) {}; +func int Npc_GetActiveSpellIsScroll(var instance n0) {}; +func int Npc_GetActiveSpellLevel(var c_npc self) {}; +func int Npc_GetActiveSpell(var c_npc self) {}; +func int Npc_GetAttitude(var c_npc self, var c_npc other) {}; +func int Npc_GetBodyState(var c_npc self) {}; +func int Npc_GetComrades(var instance n0) {}; +func string Npc_GetDetectedMob(var c_npc self) {}; +func int Npc_GetDistToItem(var c_npc npc, var c_item item) {}; +func int Npc_GetDistToNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_GetDistToPlayer(var c_npc npc1) {}; +func int Npc_GetDistToWP(var c_npc self, var string wpname) {}; +func c_item Npc_GetEquippedArmor(var c_npc n0) {}; +func c_item Npc_GetEquippedMeleeWeapon(var c_npc n0) {}; +func c_item Npc_GetEquippedRangedWeapon(var c_npc n0) {}; +func int Npc_GetGuildAttitude(var c_npc npc, var c_npc npc) {}; +func int Npc_GetHeightToItem(var instance n0, var instance n1) {}; +func int Npc_GetHeightToNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_GetInvItemBySlot(var c_npc self, var int category, var int slotnr) {}; +func c_item Npc_GetInvItem(var c_npc self, var int iteminstance) {}; +func int Npc_GetLastHitSpellCat(var c_npc self) {}; +func int Npc_GetLastHitSpellID(var c_npc self) {}; +func instance Npc_GetLookAtTarget(var instance n0) {}; +func string Npc_GetNearestWP(var c_npc self) {}; +func c_npc Npc_GetNewsOffender(var c_npc self, var int newsnumber) {}; +func c_npc Npc_GetNewsVictim(var c_npc self, var int newsnumber) {}; +func c_npc Npc_GetNewsWitness(var c_npc self, var int newsnumber) {}; +func int Npc_GetNextTarget(var c_npc self) {}; +func string Npc_GetNextWP(var c_npc self) {}; +func int Npc_GetPermAttitude(var c_npc self, var c_npc other) {}; +func int Npc_GetPortalGuild(var instance n0) {}; +func instance Npc_GetPortalOwner(var instance n0) {}; +func c_item Npc_GetReadiedWeapon(var c_npc n0) {}; +func int Npc_GetStateTime(var c_npc self) {}; +func int Npc_GetTalentSkill(var instance n0, var int i1) {}; +func int Npc_GetTalentValue(var instance n0, var int i1) {}; +func int Npc_GetTarget(var c_npc self) {}; +func int Npc_GetTrueGuild(var c_npc npc) {}; +func int NPC_GiveInfo(var c_npc npc, var int important) {}; +func int Npc_GiveInfo(var instance n0, var int i1) {}; +func void Npc_GiveItem(var c_npc n0, var c_item n1, var c_npc n2) {}; +func int Npc_HasBodyFlag(var c_npc self, var int bodyflag) {}; +func int Npc_HasDetectedNpc(var c_npc self, var c_npc other) {}; +func int Npc_HasEquippedArmor(var c_npc self) {}; +func int Npc_HasEquippedMeleeWeapon(var c_npc self) {}; +func int Npc_HasEquippedRangedWeapon(var c_npc self) {}; +func int Npc_HasEquippedWeapon(var c_npc self) {}; +func int Npc_HasFightTalent(var c_npc self, var int tal) {}; +func int Npc_HasItems(var c_npc n0, var int iteminstance) {}; +func int Npc_HasNews(var c_npc self, var int newsid, var c_npc offender, var c_npc victim) {}; +func int Npc_HasOffered(var c_npc self, var c_npc other, var int iteminstance) {}; +func int Npc_HasRangedWeaponWithAmmo(var c_npc npc) {}; +func int Npc_HasReadiedMeleeWeapon(var c_npc self) {}; +func int Npc_HasReadiedRangedWeapon(var c_npc self) {}; +func int Npc_HasReadiedWeapon(var c_npc self) {}; +func int Npc_HasSpell(var c_npc self, var int spellid) {}; +func int Npc_HasTalent(var c_npc self, var int tal) {}; +func void Npc_ChangeAttribute(var c_npc self, var int atr, var int value) {}; +func int Npc_CheckAvailableMission(var c_npc npc, var int missionstate, var int important) {}; +func int Npc_CheckInfo(var c_npc npc, var int important) {}; +func int Npc_CheckOfferMission(var c_npc npc, var int important) {}; +func int Npc_CheckRunningMission(var c_npc npc, var int important) {}; +func int Npc_IsAiming(var c_npc self, var c_npc other) {}; +func int Npc_IsDead(var c_npc n0) {}; +func int Npc_IsDetectedMobOwnedByGuild(var c_npc user, var int ownerguild) {}; +func int Npc_IsDetectedMobOwnedByNpc(var c_npc user, var c_npc owner) {}; +func int Npc_IsDrawingSpell(var instance n0) {}; +func int Npc_IsDrawingWeapon(var instance n0) {}; +func int Npc_IsInCutscene(var c_npc self) {}; +func int Npc_IsInFightMode(var c_npc self, var int fmode) {}; +func int Npc_IsInPlayersRoom(var instance n0) {}; +func int Npc_IsInRoutine(var c_npc self, var func state) {}; +func int Npc_IsInState(var c_npc self, var func state) {}; +func int Npc_IsNear(var c_npc self, var c_npc other) {}; +func int Npc_IsNewsGossip(var c_npc self, var int newsnumber) {}; +func int Npc_IsNextTargetAvailable(var c_npc self) {}; +func int Npc_IsOnFP(var c_npc self, var string name) {}; +func int Npc_IsPlayerInMyRoom(var c_npc npc) {}; +func int Npc_IsPlayer(var c_npc player) {}; +func int Npc_IsVoiceActive(var instance n0) {}; +func int Npc_IsWayBlocked(var c_npc self) {}; +func int Npc_KnowsInfo(var c_npc self, var int infoinstance) {}; +func int Npc_KnowsPlayer(var c_npc self, var c_npc player) {}; +func void Npc_LearnSpell(var c_npc self, var int spellnr) {}; +func void Npc_MemoryEntryGuild(var c_npc self, var int source, var c_npc offender, var int newsid, var c_npc victimguild) {}; +func void Npc_MemoryEntry(var c_npc self, var int source, var c_npc offender, var int newsid, var c_npc victim) {}; +func int Npc_OwnedByGuild(var c_item item, var int guild) {}; +func int Npc_OwnedByNpc(var c_item item, var c_npc npc) {}; +func void Npc_PercDisable(var c_npc self, var int percid) {}; +func void Npc_PerceiveAll(var c_npc self) {}; +func void Npc_PercEnable(var c_npc self, var int percid, var func function) {}; +func void Npc_PlayAni(var instance n0, var string s1) {}; +func int Npc_RefuseTalk(var c_npc self) {}; +func void Npc_RemoveInvItems(var c_npc owner, var int iteminstance, var int amount) {}; +func void Npc_RemoveInvItem(var c_npc owner, var int iteminstance) {}; +func void Npc_SendPassivePerc(var c_npc npc1, var int perc_type, var c_npc npc2, var c_npc npc3) {}; +func void Npc_SendSinglePerc(var c_npc self, var c_npc target, var int percid) {}; +func int Npc_SetActiveSpellInfo(var c_npc npc, var int i1) {}; +func void Npc_SetAttitude(var c_npc self, var int att) {}; +func void Npc_SetKnowsPlayer(var c_npc self, var c_npc player) {}; +func void Npc_SetPercTime(var c_npc self, var float seconds) {}; +func void Npc_SetRefuseTalk(var c_npc self, var int timesec) {}; +func void Npc_SetStateTime(var c_npc self, var int seconds) {}; +func void Npc_SetTalentSkill(var instance n0, var int i1, var int i2) {}; +func void Npc_SetTalentValue(var instance n0, var int i1, var int i2) {}; +func void Npc_SetTarget(var c_npc self, var c_npc other) {}; +func void Npc_SetTeleportPos(var c_npc self) {}; +func void Npc_SetTempAttitude(var c_npc self, var int att) {}; +func void Npc_SetToFightMode(var c_npc self, var int weapon) {}; +func void Npc_SetToFistMode(var c_npc self) {}; +func int Npc_SetTrueGuild(var c_npc npc, var int guildid) {}; +func int Npc_StartItemReactModules(var c_npc self, var c_npc other, var c_item item) {}; +func void Npc_StopAni(var instance n0, var string s1) {}; +func int Npc_WasInState(var c_npc self, var func state) {}; +func int Npc_WasPlayerInMyRoom(var c_npc npc) {}; +func void Perc_SetRange(var int percid, var int range) {}; +func int PlayVideoEx(var string filename, var int screenblend, var int exitsession) {}; +func int PlayVideo(var string filename) {}; +func void PrintDebugCh(var int ch, var string text) {}; +func void PrintDebugInstCh(var int ch, var string text) {}; +func void PrintDebugInst(var string text) {}; +func void PrintDebug(var string s) {}; +func int PrintDialog(var int i0, var string s1, var int i2, var int i3, var string s4, var int i5) {}; +func void PrintMulti(var string s0, var string s1, var string s2, var string s3, var string s4) {}; +func void PrintScreen(var string msg, var int posx, var int posy, var string font, var int timesec) {}; +func void Print(var string s0) {}; +func void Rtn_Exchange(var string oldroutine, var string newroutine) {}; +func void SetPercentDone(var int percentdone) {}; +func int Snd_GetDistToSource(var c_npc self) {}; +func int Snd_IsSourceItem(var c_npc self) {}; +func int Snd_IsSourceNpc(var c_npc self) {}; +func void Snd_Play(var string s0) {}; +func void Snd_Play3D(var c_npc n0, var string s1) {}; +func void TA_BeginOverlay(var c_npc self) {}; +func void TA_CS(var c_npc self, var string csname, var string rolename) {}; +func void TA_EndOverlay(var c_npc self) {}; +func void Tal_Configure(var int i0, var int i1) {}; +func void TA_Min(var c_npc self, var int start_h, var int start_m, var int stop_h, var int stop_m, var func state, var string waypoint) {}; +func void TA_RemoveOverlay(var c_npc self) {}; +func void TA(var c_npc self, var int start_h, var int stop_h, var func state, var string waypoint) {}; +func void Update_ChoiceBox(var string s0) {}; +func void Wld_AssignRoomToGuild(var string s0, var int guild) {}; +func void Wld_AssignRoomToNpc(var string s0, var c_npc roomowner) {}; +func int Wld_DetectItem(var c_npc self, var int flags) {}; +func int Wld_DetectNpcExAtt(var instance n0, var int i1, var func f2, var int i3, var int i4, var int i5) {}; +func int Wld_DetectNpcEx(var instance n0, var int i1, var func f2, var int i3, var int i4) {}; +func int Wld_DetectNpc(var c_npc self, var int instance, var func aistate, var int guild) {}; +func int Wld_DetectPlayer(var c_npc self) {}; +func void Wld_ExchangeGuildAttitudes(var string name) {}; +func int Wld_GetDay() {}; +func int Wld_GetFormerPlayerPortalGuild() {}; +func c_npc Wld_GetFormerPlayerPortalOwner() {}; +func int Wld_GetGuildAttitude(var int guild1, var int guild2) {}; +func int Wld_GetMobState(var c_npc self, var string schemename) {}; +func int Wld_GetPlayerPortalGuild() {}; +func c_npc Wld_GetPlayerPortalOwner() {}; +func void Wld_InsertItem(var int iteminstance, var string spawnpoint) {}; +func void Wld_InsertNpcAndRespawn(var int instance, var string spawnpoint, var float spawndelay) {}; +func void Wld_InsertNpc(var int npcinstance, var string spawnpoint) {}; +func void Wld_InsertObject(var string s0, var string s1) {}; +func int Wld_IsFPAvailable(var c_npc self, var string fpname) {}; +func int Wld_IsFpAvailable(var instance n0, var string s1) {}; +func int Wld_IsMobAvailable(var c_npc self, var string schemename) {}; +func int Wld_IsNextFPAvailable(var c_npc self, var string fpname) {}; +func int Wld_IsNextFpAvailable(var instance n0, var string s1) {}; +func int Wld_IsRaining() {}; +func int Wld_IsTime(var int hour1, var int min1, var int hour2, var int min2) {}; +func void Wld_PlayEffect(var string effectinstance, var int originvob, var int targetvob, var int effectlevel, var int damage, var int damagetype, var int bisprojectile) {}; +func int Wld_RemoveItem(var c_item item) {}; +func void Wld_RemoveNpc(var int i0) {}; +func void Wld_SendTrigger(var string vobname) {}; +func void Wld_SendUntrigger(var string vobname) {}; +func void Wld_SetGuildAttitude(var int guild1, var int attitude, var int guild2) {}; +func void Wld_SetMobRoutine(var int hour1, var int min1, var string objname, var int state) {}; +func void Wld_SetObjectRoutine(var int hour1, var int min1, var string objname, var int state) {}; +func void Wld_SetTime(var int hour, var int min) {}; +func void Wld_SpawnNpcRange(var instance n0, var int i1, var int i2, var float r3) {}; diff --git a/docs/zengin/scripts/externals/externals_clean.d b/docs/zengin/scripts/externals/externals_clean.d new file mode 100644 index 0000000000..0d67d9eea6 --- /dev/null +++ b/docs/zengin/scripts/externals/externals_clean.d @@ -0,0 +1,350 @@ +func void AI_AimAt(var c_npc attacker, var c_npc target) {}; +func void AI_AlignToFP(var c_npc self) {}; +func void AI_AlignToWP(var c_npc self) {}; +func void AI_AskText(var c_npc self, var func funcyes, var func funcno, var string stryes, var string strno) {}; +func void AI_Ask(var c_npc self, var func anseryes, var func answerno) {}; +func void AI_Attack(var c_npc self) {}; +func void AI_CanSeeNpc(var instance n0, var instance n1, var func f2) {}; +func void AI_CombatReactToDamage(var instance n0) {}; +func void AI_ContinueRoutine(var c_npc self) {}; +func void AI_Defend(var c_npc self) {}; +func void AI_Dodge(var c_npc npc) {}; +func void AI_DrawWeapon(var c_npc n0) {}; +func void AI_DropItem(var c_npc self, var int itemid) {}; +func void AI_DropMob(var instance n0) {}; +func void AI_EquipArmor(var c_npc owner, var c_item armor_from_owners_inventory) {}; +func void AI_EquipBestArmor(var c_npc self) {}; +func void AI_EquipBestMeleeWeapon(var c_npc self) {}; +func void AI_EquipBestRangedWeapon(var c_npc self) {}; +func void AI_FinishingMove(var c_npc self, var c_npc other) {}; +func void AI_Flee(var c_npc self) {}; +func void AI_GotoFP(var c_npc self, var string fpname) {}; +func void AI_GotoItem(var c_npc self, var c_item item) {}; +func void AI_GotoNextFP(var c_npc self, var string fpname) {}; +func void AI_GotoNpc(var c_npc self, var c_npc other) {}; +func void AI_GotoSound(var c_npc n0) {}; +func void AI_GotoWP(var c_npc n0, var string s0) {}; +func void AI_LookAtNpc(var c_npc self, var c_npc other) {}; +func void AI_LookAt(var c_npc self, var string name) {}; +func void AI_LookForItem(var c_npc self, var int instance) {}; +func void AI_OutputSVM_Overlay(var c_npc self, var c_npc target, var string svmname) {}; +func void AI_OutputSVM(var c_npc self, var c_npc target, var string svmname) {}; +func void AI_Output(var c_npc self, var c_npc target, var string outputname) {}; +func void AI_PlayAniBS(var c_npc npc, var string aniname, var int bodystate) {}; +func void AI_PlayAni(var c_npc n0, var string s0) {}; +func void AI_PlayCutscene(var c_npc self, var string csname) {}; +func void AI_PlayFX(var instance n0, var instance n1, var string s2) {}; +func void AI_PointAtNpc(var c_npc self, var c_npc other) {}; +func void AI_PointAt(var c_npc self, var string name) {}; +func int AI_PrintScreen(var string s0, var int i1, var int i2, var string s3, var int i4) {}; +func void AI_ProcessInfos(var instance n0) {}; +func void AI_Quicklook(var c_npc self, var c_npc other) {}; +func void AI_QuickLook(var instance n0, var instance n1) {}; +func void AI_ReadyMeleeWeapon(var c_npc self) {}; +func void AI_ReadyRangedWeapon(var c_npc self) {}; +func void AI_ReadySpell(var c_npc self, var int spellid, var int investmana) {}; +func void AI_RemoveWeapon(var c_npc n0) {}; +func void AI_SetNpcsToState(var c_npc self, var func aistatefunc, var int radius) {}; +func void AI_SetWalkmode(var c_npc n, var int n0) {}; +func void AI_SetWalkMode(var instance n0, var int i1) {}; +func void AI_ShootAt(var c_npc attacker, var c_npc target) {}; +func void AI_Snd_Play(var instance n0, var string s1) {}; +func void AI_Snd_Play3D(var instance n0, var instance n1, var string s2) {}; +func void AI_StandUpQuick(var c_npc self) {}; +func void AI_StandUp(var c_npc self) {}; +func void AI_StartState(var c_npc self, var func what, var int statebehaviour, var string wpname) {}; +func void AI_StopAim(var c_npc attacker) {}; +func void AI_StopFX(var instance n0, var string s1) {}; +func void AI_StopLookAt(var c_npc self) {}; +func void AI_StopPointAt(var c_npc self) {}; +func void AI_StopProcessInfos(var c_npc npc) {}; +func void AI_TakeItem(var c_npc self, var c_item item) {}; +func void AI_TakeMob(var instance n0, var string s1) {}; +func void AI_Teleport(var c_npc self, var string waypoint) {}; +func void AI_TurnAway(var c_npc n0, var c_npc n1) {}; +func void AI_TurnToNpc(var c_npc n0, var c_npc n1) {}; +func void AI_TurnToSound(var c_npc self) {}; +func void AI_UnequipArmor(var c_npc self) {}; +func void AI_UnequipWeapons(var c_npc self) {}; +func void AI_UnreadySpell(var c_npc self) {}; +func void AI_UseItemToState(var c_npc self, var int iteminstance, var int state) {}; +func void AI_UseItem(var c_npc self, var int iteminstance) {}; +func int AI_UseMob(var c_npc self, var string schemename, var int targetstate) {}; +func void AI_WaitForQuestion(var c_npc self, var func scriptfunc) {}; +func void AI_WaitMS(var instance n0, var int i1) {}; +func void AI_WaitTillEnd(var c_npc self, var c_npc other) {}; +func void AI_Wait(var c_npc n0, var float n1) {}; +func void AI_WhirlAroundToSource(var instance n0) {}; +func void AI_WhirlAround(var c_npc self, var c_npc other) {}; +func void Apply_Options_Audio() {}; +func void Apply_Options_Controls() {}; +func void Apply_Options_Game() {}; +func void Apply_Options_Performance() {}; +func void Apply_Options_Video() {}; +func string ConcatStrings(var string str1, var string str2) {}; +func void CreateInvItems(var c_npc n0, var int n1, var int n2) {}; +func void CreateInvItem(var c_npc n0, var int n1) {}; +func int Doc_Create() {}; +func int Doc_CreateMap() {}; +func void Doc_Font (var string Font) {}; +func void Doc_Font(var string s0) {}; +func void Doc_MapCoordinates (var string Level, var float GameX1, var float GameY1, var float PixelX1, var float PixelY1, var float GameX2, var float GameY2, var float PixelX2, var float PixelY2) {}; +func void Doc_MapCoordinates(var string s0, var float r1, var float r2, var float r3, var float r4, var float r5, var float r6, var float r7, var float r8) {}; +func void Doc_Open(var string s0) {}; +func void Doc_Open (var string Texture) {}; +func void Doc_PrintLines(var int document, var int page, var string text) {}; +func void Doc_PrintLine(var int document, var int page, var string text) {}; +func void Doc_Print(var string s0) {}; +func void Doc_Print (var string Text) {}; +func void Doc_SetFont(var int document, var int page, var string font) {}; +func void Doc_SetLevelCoords(var int document, var int left, var int top, var int right, var int bottom) {}; +func void Doc_SetLevel(var int document, var string level) {}; +func void Doc_SetMargins(var int document, var int page, var int left, var int top, var int right, var int bottom, var int pixels) {}; +func void Doc_SetPages(var int document, var int count) {}; +func void Doc_SetPage(var int document, var int page, var string texture, var int scale) {}; +func void Doc_Show(var int document) {}; +func void EquipItem(var c_npc n0, var int n1) {}; +func void ExitGame() {}; +func void ExitSession() {}; +func int FloatToInt(var float x) {}; +func string FloatToString(var float r0) {}; +func void Game_InitEnglish() {}; +func void Game_InitGerman() {}; +func int Hlp_CutscenePlayed(var string csname) {}; +func int Hlp_GetInstanceID(var c_item item) {}; +func c_npc Hlp_GetNpc(var int instancename) {}; +func int Hlp_IsItem(var c_item item, var int instancename) {}; +func int Hlp_IsValidItem(var c_item item) {}; +func int Hlp_IsValidNpc(var c_npc self) {}; +func int Hlp_Random(var int n0) {}; +func int Hlp_StrCmp(var string s1, var string s2) {}; +func void Info_AddChoice(var int i0, var string s1, var func f2) {}; +func void Info_ClearChoices(var int i0) {}; +func int InfoManager_HasFinished() {}; +func void IntroduceChapter(var string titel, var string untertitel, var string texture, var string sound, var int waittime) {}; +func float IntToFloat(var int x) {}; +func string IntToString(var int x) {}; + +/// Creates a new log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in +func void Log_CreateTopic(var string topicName, var int logSection) {}; +/// Adds an entry to a log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param entry content of the new entry +func void Log_AddEntry(var string topicName, var string entry) {}; +/// Changes the status of the topic with the name `topicName` +/// +/// @param topicName unique string used to identify and name the topic +/// @param status [LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE] the status to be set +func void Log_SetTopicStatus(var string TopicName, var int status) {}; + +func void Mdl_ApplyOverlayMDSTimed(var c_npc self, var string overlayname, var float timeticks) {}; +func void Mdl_ApplyOverlayMdsTimed(var instance n0, var string s1, var int i2) {}; +func void Mdl_ApplyOverlayMds(var c_npc n0, var string s1) {}; +func void Mdl_ApplyOverlayMDS(var instance n0, var string s1) {}; +func void Mdl_ApplyRandomAniFreq(var c_npc n0, var string s1, var float f2) {}; +func void Mdl_ApplyRandomAni(var c_npc n0, var string s1, var string s2) {}; +func void Mdl_ApplyRandomFaceAni(var c_npc self, var string name, var float timemin, var float timeminvar, var float timemax, var float timemaxvar, var float probmin) {}; +func void Mdl_RemoveOverlayMDS(var c_npc self, var string overlayname) {}; +func void Mdl_SetModelFatness(var c_npc self, var float fatness) {}; +func void Mdl_SetModelScale(var c_npc self, var float x, var float y, var float z) {}; +func void Mdl_SetVisualBody(var instance n0, var string s1, var int i2, var int i3, var string s4, var int i5, var int i6, var int i7) {}; +func void Mdl_SetVisual(var instance n0, var string s1) {}; +func void Mdl_StartFaceAni(var c_npc self, var string name, var float intensity, var float holdtime) {}; +func void Mis_AddMissionEntry(var instance n0, var string s1) {}; +func int Mis_GetStatus(var int missionname) {}; +func int Mis_OnTime(var int missionname) {}; +func void Mis_RemoveMission(var instance n0) {}; +func void Mis_SetStatus(var int missionname, var int newstatus) {}; +func void Mob_CreateItems(var string mobname, var int iteminstance, var int amount) {}; +func int Mob_HasItems(var string mobname, var int iteminstance) {}; +func int Npc_AreWeStronger(var c_npc self, var c_npc other) {}; +func int Npc_CanSeeItem(var c_npc npc1, var c_item item) {}; +func int Npc_CanSeeNpcFreeLOS(var c_npc self, var c_npc other) {}; +func int Npc_CanSeeNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_CanSeeSource(var c_npc self) {}; +func void Npc_ClearAIQueue(var c_npc self) {}; +func void Npc_ClearInventory(var instance n0) {}; +func void Npc_CreateSpell(var c_npc self, var int spellnr) {}; +func int Npc_DeleteNews(var instance n0, var int i1) {}; +func void Npc_ExchangeRoutine(var c_npc self, var string routinename) {}; +func int Npc_GetActiveSpellCat(var c_npc self) {}; +func int Npc_GetActiveSpellIsScroll(var instance n0) {}; +func int Npc_GetActiveSpellLevel(var c_npc self) {}; +func int Npc_GetActiveSpell(var c_npc self) {}; +func int Npc_GetAttitude(var c_npc self, var c_npc other) {}; +func int Npc_GetBodyState(var c_npc self) {}; +func int Npc_GetComrades(var instance n0) {}; +func string Npc_GetDetectedMob(var c_npc self) {}; +func int Npc_GetDistToItem(var c_npc npc, var c_item item) {}; +func int Npc_GetDistToNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_GetDistToPlayer(var c_npc npc1) {}; +func int Npc_GetDistToWP(var c_npc self, var string wpname) {}; +func c_item Npc_GetEquippedArmor(var c_npc n0) {}; +func c_item Npc_GetEquippedMeleeWeapon(var c_npc n0) {}; +func c_item Npc_GetEquippedRangedWeapon(var c_npc n0) {}; +func int Npc_GetGuildAttitude(var c_npc npc, var c_npc npc) {}; +func int Npc_GetHeightToItem(var instance n0, var instance n1) {}; +func int Npc_GetHeightToNpc(var c_npc npc1, var c_npc npc2) {}; +func int Npc_GetInvItemBySlot(var c_npc self, var int category, var int slotnr) {}; +func c_item Npc_GetInvItem(var c_npc self, var int iteminstance) {}; +func int Npc_GetLastHitSpellCat(var c_npc self) {}; +func int Npc_GetLastHitSpellID(var c_npc self) {}; +func instance Npc_GetLookAtTarget(var instance n0) {}; +func string Npc_GetNearestWP(var c_npc self) {}; +func c_npc Npc_GetNewsOffender(var c_npc self, var int newsnumber) {}; +func c_npc Npc_GetNewsVictim(var c_npc self, var int newsnumber) {}; +func c_npc Npc_GetNewsWitness(var c_npc self, var int newsnumber) {}; +func int Npc_GetNextTarget(var c_npc self) {}; +func string Npc_GetNextWP(var c_npc self) {}; +func int Npc_GetPermAttitude(var c_npc self, var c_npc other) {}; +func int Npc_GetPortalGuild(var instance n0) {}; +func instance Npc_GetPortalOwner(var instance n0) {}; +func c_item Npc_GetReadiedWeapon(var c_npc n0) {}; +func int Npc_GetStateTime(var c_npc self) {}; +func int Npc_GetTalentSkill(var instance n0, var int i1) {}; +func int Npc_GetTalentValue(var instance n0, var int i1) {}; +func int Npc_GetTarget(var c_npc self) {}; +func int Npc_GetTrueGuild(var c_npc npc) {}; +func int NPC_GiveInfo(var c_npc npc, var int important) {}; +func int Npc_GiveInfo(var instance n0, var int i1) {}; +func void Npc_GiveItem(var c_npc n0, var c_item n1, var c_npc n2) {}; +func int Npc_HasBodyFlag(var c_npc self, var int bodyflag) {}; +func int Npc_HasDetectedNpc(var c_npc self, var c_npc other) {}; +func int Npc_HasEquippedArmor(var c_npc self) {}; +func int Npc_HasEquippedMeleeWeapon(var c_npc self) {}; +func int Npc_HasEquippedRangedWeapon(var c_npc self) {}; +func int Npc_HasEquippedWeapon(var c_npc self) {}; +func int Npc_HasFightTalent(var c_npc self, var int tal) {}; +func int Npc_HasItems(var c_npc n0, var int iteminstance) {}; +func int Npc_HasNews(var c_npc self, var int newsid, var c_npc offender, var c_npc victim) {}; +func int Npc_HasOffered(var c_npc self, var c_npc other, var int iteminstance) {}; +func int Npc_HasRangedWeaponWithAmmo(var c_npc npc) {}; +func int Npc_HasReadiedMeleeWeapon(var c_npc self) {}; +func int Npc_HasReadiedRangedWeapon(var c_npc self) {}; +func int Npc_HasReadiedWeapon(var c_npc self) {}; +func int Npc_HasSpell(var c_npc self, var int spellid) {}; +func int Npc_HasTalent(var c_npc self, var int tal) {}; +func void Npc_ChangeAttribute(var c_npc self, var int atr, var int value) {}; +func int Npc_CheckAvailableMission(var c_npc npc, var int missionstate, var int important) {}; +func int Npc_CheckInfo(var c_npc npc, var int important) {}; +func int Npc_CheckOfferMission(var c_npc npc, var int important) {}; +func int Npc_CheckRunningMission(var c_npc npc, var int important) {}; +func int Npc_IsAiming(var c_npc self, var c_npc other) {}; +func int Npc_IsDead(var c_npc n0) {}; +func int Npc_IsDetectedMobOwnedByGuild(var c_npc user, var int ownerguild) {}; +func int Npc_IsDetectedMobOwnedByNpc(var c_npc user, var c_npc owner) {}; +func int Npc_IsDrawingSpell(var instance n0) {}; +func int Npc_IsDrawingWeapon(var instance n0) {}; +func int Npc_IsInCutscene(var c_npc self) {}; +func int Npc_IsInFightMode(var c_npc self, var int fmode) {}; +func int Npc_IsInPlayersRoom(var instance n0) {}; +func int Npc_IsInRoutine(var c_npc self, var func state) {}; +func int Npc_IsInState(var c_npc self, var func state) {}; +func int Npc_IsNear(var c_npc self, var c_npc other) {}; +func int Npc_IsNewsGossip(var c_npc self, var int newsnumber) {}; +func int Npc_IsNextTargetAvailable(var c_npc self) {}; +func int Npc_IsOnFP(var c_npc self, var string name) {}; +func int Npc_IsPlayerInMyRoom(var c_npc npc) {}; +func int Npc_IsPlayer(var c_npc player) {}; +func int Npc_IsVoiceActive(var instance n0) {}; +func int Npc_IsWayBlocked(var c_npc self) {}; +func int Npc_KnowsInfo(var c_npc self, var int infoinstance) {}; +func int Npc_KnowsPlayer(var c_npc self, var c_npc player) {}; +func void Npc_LearnSpell(var c_npc self, var int spellnr) {}; +func void Npc_MemoryEntryGuild(var c_npc self, var int source, var c_npc offender, var int newsid, var c_npc victimguild) {}; +func void Npc_MemoryEntry(var c_npc self, var int source, var c_npc offender, var int newsid, var c_npc victim) {}; +func int Npc_OwnedByGuild(var c_item item, var int guild) {}; +func int Npc_OwnedByNpc(var c_item item, var c_npc npc) {}; +func void Npc_PercDisable(var c_npc self, var int percid) {}; +func void Npc_PerceiveAll(var c_npc self) {}; +func void Npc_PercEnable(var c_npc self, var int percid, var func function) {}; +func void Npc_PlayAni(var instance n0, var string s1) {}; +func int Npc_RefuseTalk(var c_npc self) {}; +func void Npc_RemoveInvItems(var c_npc owner, var int iteminstance, var int amount) {}; +func void Npc_RemoveInvItem(var c_npc owner, var int iteminstance) {}; +func void Npc_SendPassivePerc(var c_npc npc1, var int perc_type, var c_npc npc2, var c_npc npc3) {}; +func void Npc_SendSinglePerc(var c_npc self, var c_npc target, var int percid) {}; +func int Npc_SetActiveSpellInfo(var c_npc npc, var int i1) {}; +func void Npc_SetAttitude(var c_npc self, var int att) {}; +func void Npc_SetKnowsPlayer(var c_npc self, var c_npc player) {}; +func void Npc_SetPercTime(var c_npc self, var float seconds) {}; +func void Npc_SetRefuseTalk(var c_npc self, var int timesec) {}; +func void Npc_SetStateTime(var c_npc self, var int seconds) {}; +func void Npc_SetTalentSkill(var instance n0, var int i1, var int i2) {}; +func void Npc_SetTalentValue(var instance n0, var int i1, var int i2) {}; +func void Npc_SetTarget(var c_npc self, var c_npc other) {}; +func void Npc_SetTeleportPos(var c_npc self) {}; +func void Npc_SetTempAttitude(var c_npc self, var int att) {}; +func void Npc_SetToFightMode(var c_npc self, var int weapon) {}; +func void Npc_SetToFistMode(var c_npc self) {}; +func int Npc_SetTrueGuild(var c_npc npc, var int guildid) {}; +func int Npc_StartItemReactModules(var c_npc self, var c_npc other, var c_item item) {}; +func void Npc_StopAni(var instance n0, var string s1) {}; +func int Npc_WasInState(var c_npc self, var func state) {}; +func int Npc_WasPlayerInMyRoom(var c_npc npc) {}; +func void Perc_SetRange(var int percid, var int range) {}; +func int PlayVideoEx(var string filename, var int screenblend, var int exitsession) {}; +func int PlayVideo(var string filename) {}; +func void PrintDebugCh(var int ch, var string text) {}; +func void PrintDebugInstCh(var int ch, var string text) {}; +func void PrintDebugInst(var string text) {}; +func void PrintDebug(var string s) {}; +func int PrintDialog(var int i0, var string s1, var int i2, var int i3, var string s4, var int i5) {}; +func void PrintMulti(var string s0, var string s1, var string s2, var string s3, var string s4) {}; +func void PrintScreen(var string msg, var int posx, var int posy, var string font, var int timesec) {}; +func void Print(var string s0) {}; +func void Rtn_Exchange(var string oldroutine, var string newroutine) {}; +func void SetPercentDone(var int percentdone) {}; +func int Snd_GetDistToSource(var c_npc self) {}; +func int Snd_IsSourceItem(var c_npc self) {}; +func int Snd_IsSourceNpc(var c_npc self) {}; +func void Snd_Play(var string s0) {}; +func void Snd_Play3D(var c_npc n0, var string s1) {}; +func void TA_BeginOverlay(var c_npc self) {}; +func void TA_CS(var c_npc self, var string csname, var string rolename) {}; +func void TA_EndOverlay(var c_npc self) {}; +func void Tal_Configure(var int i0, var int i1) {}; +func void TA_Min(var c_npc self, var int start_h, var int start_m, var int stop_h, var int stop_m, var func state, var string waypoint) {}; +func void TA_RemoveOverlay(var c_npc self) {}; +func void TA(var c_npc self, var int start_h, var int stop_h, var func state, var string waypoint) {}; +func void Update_ChoiceBox(var string s0) {}; +func void Wld_AssignRoomToGuild(var string s0, var int guild) {}; +func void Wld_AssignRoomToNpc(var string s0, var c_npc roomowner) {}; +func int Wld_DetectItem(var c_npc self, var int flags) {}; +func int Wld_DetectNpcExAtt(var instance n0, var int i1, var func f2, var int i3, var int i4, var int i5) {}; +func int Wld_DetectNpcEx(var instance n0, var int i1, var func f2, var int i3, var int i4) {}; +func int Wld_DetectNpc(var c_npc self, var int instance, var func aistate, var int guild) {}; +func int Wld_DetectPlayer(var c_npc self) {}; +func void Wld_ExchangeGuildAttitudes(var string name) {}; +func int Wld_GetDay() {}; +func int Wld_GetFormerPlayerPortalGuild() {}; +func c_npc Wld_GetFormerPlayerPortalOwner() {}; +func int Wld_GetGuildAttitude(var int guild1, var int guild2) {}; +func int Wld_GetMobState(var c_npc self, var string schemename) {}; +func int Wld_GetPlayerPortalGuild() {}; +func c_npc Wld_GetPlayerPortalOwner() {}; +func void Wld_InsertItem(var int iteminstance, var string spawnpoint) {}; +func void Wld_InsertNpcAndRespawn(var int instance, var string spawnpoint, var float spawndelay) {}; +func void Wld_InsertNpc(var int npcinstance, var string spawnpoint) {}; +func void Wld_InsertObject(var string s0, var string s1) {}; +func int Wld_IsFPAvailable(var c_npc self, var string fpname) {}; +func int Wld_IsFpAvailable(var instance n0, var string s1) {}; +func int Wld_IsMobAvailable(var c_npc self, var string schemename) {}; +func int Wld_IsNextFPAvailable(var c_npc self, var string fpname) {}; +func int Wld_IsNextFpAvailable(var instance n0, var string s1) {}; +func int Wld_IsRaining() {}; +func int Wld_IsTime(var int hour1, var int min1, var int hour2, var int min2) {}; +func void Wld_PlayEffect(var string effectinstance, var int originvob, var int targetvob, var int effectlevel, var int damage, var int damagetype, var int bisprojectile) {}; +func int Wld_RemoveItem(var c_item item) {}; +func void Wld_RemoveNpc(var int i0) {}; +func void Wld_SendTrigger(var string vobname) {}; +func void Wld_SendUntrigger(var string vobname) {}; +func void Wld_SetGuildAttitude(var int guild1, var int attitude, var int guild2) {}; +func void Wld_SetMobRoutine(var int hour1, var int min1, var string objname, var int state) {}; +func void Wld_SetObjectRoutine(var int hour1, var int min1, var string objname, var int state) {}; +func void Wld_SetTime(var int hour, var int min) {}; +func void Wld_SpawnNpcRange(var instance n0, var int i1, var int i2, var float r3) {}; diff --git a/docs/zengin/scripts/externals/index.md b/docs/zengin/scripts/externals/index.md new file mode 100644 index 0000000000..696bcdde8f --- /dev/null +++ b/docs/zengin/scripts/externals/index.md @@ -0,0 +1,3 @@ +# Externals +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. diff --git a/docs/zengin/scripts/externals/log.md b/docs/zengin/scripts/externals/log.md new file mode 100644 index 0000000000..e31119cdaf --- /dev/null +++ b/docs/zengin/scripts/externals/log.md @@ -0,0 +1,89 @@ +--- +title: Log functions +--- +# Log external functions +Log externals are used to manipulate players log and to track quest progress. + + +## `Log_CreateTopic` +Creates a new log topic with the name `topicName` under the section `logSection` + +```dae +func void Log_CreateTopic(var string topicName, var int logSection) {}; +``` +**Parameters** + +- `#!dae var string topicName` + Unique string used to identify and name the topic +- `#!dae var int logSection` + Indicates in which section to create the topic in. + Takes constants `LOG_MISSION`, `LOG_NOTE` as values + +## `Log_AddEntry` +Adds an entry to a log topic with the name `topicName` under the section `logSection` + +```dae +func void Log_AddEntry(var string topicName, var string entry) {}; +``` +**Parameters** + +- `#!dae var string topicName` + Unique string used to identify and name the topic +- `#!dae var string entry` + Content of the new entry + +!!! Info + In the engine the `#!dae Log_AddEntry()` is wrapped in a `#!dae B_LogEntry()` function. This function also handles printing the "New Journal Entry" message to the screen and playing the sound effect. + ```dae + func void B_LogEntry(var string topic, var string entry) + { + PrintDebugNpc(PD_ZS_DETAIL, "B_LogEntry"); // Logging + + Log_AddEntry(topic, entry); + + PrintScreen(NAME_NewLogEntry, -1, _YPOS_MESSAGE_LOGENTRY, "font_old_10_white.tga", _TIME_MESSAGE_LOGENTRY); + Snd_Play("LogEntry"); + }; + ``` + +## `Log_SetTopicStatus` +Changes the status of the topic with the name `topicName` + +```dae +func void Log_SetTopicStatus(var string topicName, var int status) {}; +``` +**Parameters** + +- `#!dae var string topicName` + Unique string used to identify and name the topic +- `#!dae var int status` + The status to be set. + Takes constants `LOG_RUNNING`, `LOG_SUCCESS`, `LOG_FAILED`, `LOG_OBSOLETE` as values + + +## zParserExtender +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](https://ataulien.github.io/Inside-Gothic/QuestLog/)). 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](../extenders/zparserextender/externals/log.md). + + +## Externals with docu comments + +```dae +/// Creates a new log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in +func void Log_CreateTopic(var string topicName, var int logSection) {}; + +/// Creates a new log topic with the name `topicName` under the section `logSection` +/// +/// @param topicName unique string used to identify and name the topic +/// @param logSection [LOG_MISSION, LOG_NOTE] indicates in which section to create the topic in +func void Log_AddEntry(var string topicName, var string entry) {}; + +/// Changes the status of the topic with the name `topicName` +/// +/// @param topicName unique string used to identify and name the topic +/// @param status [LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE] the status to be set +func void Log_SetTopicStatus(var string topicName, var int status) {}; +``` diff --git a/docs/zengin/scripts/externals/mdl.md b/docs/zengin/scripts/externals/mdl.md new file mode 100644 index 0000000000..20cedf29a1 --- /dev/null +++ b/docs/zengin/scripts/externals/mdl.md @@ -0,0 +1,315 @@ +--- +title: MDL functions +--- +# MDL functions +Functions to tweak animation and other model related settings. + +## `Mdl_ApplyOverlayMDS` +Apply an animation overlay with `overlay_name` for the specified `npc` +```dae +func void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the overlay to +- `#!dae var string overlay_name` + Name of the animation overlay + +## `Mdl_ApplyOverlayMDSTimed` +Apply an animation overlay with `overlay_name` for the specified `npc` for `duration` milliseconds +```dae +func void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the overlay to +- `#!dae var string overlay_name` + Name of the animation overlay +- `#!dae var float duration` + Overlay duration in milliseconds + +## `Mdl_RemoveOverlayMDS` +Remove the animation overlay `overlay_name` from specified `npc` +```dae +func void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to remove the overlay from +- `#!dae var string overlay_name` + Name of the animation overlay + +## `Mdl_ApplyRandomAni` +Assign a random animation `ani2` to random animation list of animation `ani1` +```dae +func void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC owning the animation +- `#!dae var string ani1` + The animation to assign random animation to +- `#!dae var string ani2` + Animation to be assigned + + +## `Mdl_ApplyRandomAniFreq` +Sets the random animation frequency for animation `ani1` +```dae +func void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC owning the animation +- `#!dae var string ani1` + The animation to set the random frequency +- `#!dae var float frequency` + Number of seconds between random animations + +??? Abstract "Example" + ```dae + // Attach T_WOUNDED_TRY animation to the S_WOUNDED animation + Mdl_ApplyRandomAni(self, "S_WOUNDED", "T_WOUNDED_TRY"); + // Make the random animation attached play every 8 seconds + Mdl_ApplyRandomAniFreq(self, "S_WOUNDED", 8); + ``` + +## `Mdl_SetModelFatness` +Set the procedural model fatness +```dae +func void Mdl_SetModelFatness(var c_npc npc, var float fatness) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the fatness to +- `#!dae var float fatness` + Fatness value + + +## `Mdl_SetModelScale` +Set model scale per axis +```dae +func void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the scale to +- `#!dae var float x` + Scale along the x-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% +- `#!dae var float y` + Scale along the y-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% +- `#!dae var float z` + Scale along the z-axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% + + +## `Mdl_SetVisualBody` +Sets up the visual of an NPC +```dae +func void Mdl_SetVisualBody(var instance npc, + var string body_mesh, + var int body_tex, + var int skin, + var string head_mesh, + var int head_tex, + var int teeth_tex, + var int armor_inst ) {}; +``` + +**Parameters** + +- `#!dae var instance npc` + NPC to be affected +- `#!dae var string body_mesh` + Mesh to be used as the body e.g. `HUN_BODY_NAKED0` +- `#!dae var int body_tex` + Body texture assigned to this body mesh +- `#!dae var int skin` + Body texture variant +- `#!dae var string head_mesh` + Head mesh +- `#!dae var int head_tex` + Head texture +- `#!dae var int teeth_tex` + Teeth texture +- `#!dae var int armor_inst` + Armor ([`C_ITEM`](../classes/c_item.md) instance) to be equipped or `-1` for no armor + +## `Mdl_SetVisual` +Set the animation set (also dictates models you can set using the `Mdl_SetVisualBody`) +```dae +func void Mdl_SetVisual(var instance npc, var string animation_set) {}; +``` + +**Parameters** + +- `#!dae var instance npc` + NPC to apply the animation set to +- `#!dae var string animation_set` + Name of the MDS file that contains the animation set + +## `Mdl_StartFaceAni` +Start a face animation +```dae +func void Mdl_StartFaceAni(var c_npc npc, + var string name, + var float intensity, + var float holdtime) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the animation to +- `#!dae var string name` + Animation name +- `#!dae var float intensity` + Intensity of the animation 0.0 to 1.0 +- `#!dae 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 + +## `Mdl_ApplyRandomFaceAni` +Start a random face animation +```dae +func void Mdl_ApplyRandomFaceAni(var c_npc npc, + var string name, + var float timemin, + var float timeminvar, + var float timemax, + var float timemaxvar, + var float probmin) {}; +``` + +**Parameters** + +- `#!dae var c_npc npc` + NPC to apply the animation to +- `#!dae var string name` + Animation name +- `#!dae var float timemin` + Minimum time after which the ani should be started (in seconds) +- `#!dae var float timeminvar` + Minimum boundary variation (in seconds) +- `#!dae var float timemax` + Maximum time after which the ani should be started (in seconds) +- `#!dae var float timemaxvar` + Maximum boundary variation (in seconds) +- `#!dae var float probmin` + Probability (0.0 to 1.0) to choose the lower boundary time + +## Externals with docu comments + +```dae +/// Apply an animation overlay with `overlay_name` for the specified `npc` +/// +/// @param npc NPC to apply the overlay to +/// @param overlay_name name of the animation overlay +func void Mdl_ApplyOverlayMDS(var c_npc npc, var string overlay_name) {}; + +/// Apply an animation overlay with `overlay_name` for the specified `npc` for `duration` milliseconds +/// +/// @param npc NPC to apply the overlay to +/// @param overlay_name name of the animation overlay +/// @param duration overlay duration in milliseconds +func void Mdl_ApplyOverlayMDSTimed(var c_npc npc, var string overlay_name, var float duration) {}; + +/// Remove the animation overlay `overlay_name` from specified `npc` +/// +/// @param npc NPC to remove the overlay from +/// @param overlay_name name of the animation overlay +func void Mdl_RemoveOverlayMDS(var c_npc npc, var string overlay_name) {}; + +/// Assign a random animation `ani2` to random animation list of animation `ani1` +/// +/// @param npc NPC owning the animation +/// @param ani1 the animation to assign random animation to +/// @param ani2 animation to be assigned +func void Mdl_ApplyRandomAni(var c_npc npc, var string ani1, var string ani2) {}; + +/// Sets the random animation frequency for animation `ani1` +/// +/// @param npc NPC owning the animation +/// @param ani1 the animation to set the random frequency +/// @param frequency number of seconds between random animations +func void Mdl_ApplyRandomAniFreq(var c_npc npc, var string ani1, var float frequency) {}; + +/// Set the procedural model fatness +/// +/// @param npc NPC to apply the fatness to +/// @param fatness fatness value +func void Mdl_SetModelFatness(var c_npc npc, var float fatness) {}; + +/// Set model scale per axis +/// +/// @param npc NPC to apply the scale to +/// @param x scale along the x axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% +/// @param y scale along the y axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% +/// @param z scale along the z axis, 1.0 = 100%, 1.5 = 150%, 0.9 = 90% +func void Mdl_SetModelScale(var c_npc npc, var float x, var float y, var float z) {}; + +/// Sets up the visual of an NPC +/// +/// @param npc NPC to be affected +/// @param body_mesh mesh to be used as the body e.g. `HUN_BODY_NAKED0` +/// @param body_tex body texture assigned to this body mesh +/// @param skin body texture variant +/// @param head_mesh head mesh +/// @param head_tex head texture +/// @param teeth_tex teeth texture +/// @param armor_inst armor (C_ITEM instance) to be equipped or `-1` for no armor +func void Mdl_SetVisualBody(var instance npc, + var string body_mesh, + var int body_tex, + var int skin, + var string head_mesh, + var int head_tex, + var int teeth_tex, + var int armor_inst ) {}; + +/// Set the animation set (also dictates models you can set using the `Mdl_SetVisualBody`) +/// +/// @param npc NPC to apply the animation set to +/// @param animation_set name of the MDS file that contains the animation set +func void Mdl_SetVisual(var instance npc, var string animation_set) {}; + +/// Start a face animation +/// +/// @param npc NPC to apply the animation to +/// @param name animation name +/// @param intensity intensity of the animation 0.0 to 1.0 +/// @param holdtime how long should the animation be held for `-2` will use the MMS defined value, '-1' will make the hold time infinite +func void Mdl_StartFaceAni(var c_npc npc, + var string name, + var float intensity, + var float holdtime) {}; + +/// Start a random face animation +/// +/// @param npc NPC to apply the animation to +/// @param name animation name +/// @param timemin minimum time after which the ani should be started (in seconds) +/// @param timeminvar minimum boundary variation (in seconds) +/// @param timemax maximum time after which the ani should be started (in seconds) +/// @param timemaxvar maximum boundary variation (in seconds) +/// @param probmin probability (0.0 to 1.0) to choose the lower boundary time +func void Mdl_ApplyRandomFaceAni(var c_npc npc, + var string name, + var float timemin, + var float timeminvar, + var float timemax, + var float timemaxvar, + var float probmin) {}; +``` diff --git a/docs/zengin/sound/index.md b/docs/zengin/sound/index.md index bfc0b04036..027ba1e870 100644 --- a/docs/zengin/sound/index.md +++ b/docs/zengin/sound/index.md @@ -4,7 +4,7 @@ ZenGin uses `.wav` files for playing Sound Effects and Dubbing. !!! Info In-game soundtrack isn't saved in `.wav` sound files. See [Music](../music.md). -## Poperties +## Properties Original gothic sound files has following properties: - One channel (Mono) @@ -12,7 +12,7 @@ Original gothic sound files has following properties: - 32-bit [depth](https://en.wikipedia.org/wiki/Audio_bit_depth) ## SFX -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](../anims/events.md), or in the SFX Daeduls scripts. Sounds are located in the `_work/Data/Sound/SFX` directory. +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](../anims/events.md), or in the SFX Daedalus scripts. Sounds are located in the `_work/Data/Sound/SFX` directory. ## Speech 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. diff --git a/docs/zengin/tools/index.md b/docs/zengin/tools/index.md index 25e5a314a8..8abc5e9999 100644 --- a/docs/zengin/tools/index.md +++ b/docs/zengin/tools/index.md @@ -15,12 +15,12 @@ The community has developed many tools to help with the creation of Gothic mods. - [Ninja](https://github.com/szapp/Ninja) - Ninja introduces the possibility of true modular modifications for the video games Gothic and Gothic 2 Night of the Raven. -**[VDFS tools](../general_info/vdfs)** +**[VDFS tools](../general_info/vdfs.md)** -- [GothicVDFS](vdfs_tools/gothic_vdfs.md) - NiceDE's viewer, extractor and builder for `.vdf` and `.mod` volumes +- [GothicVDFS](vdfs_tools/gothic_vdfs.md) - NicoDE's viewer, extractor and builder for `.vdf` and `.mod` volumes - [VDFS Tool](vdfs_tools/vdfs_tool.md) - Gratt's Union VDFS viewer, extractor, builder, optimizer and ZIP compressor for `.vdf` and `.mod` volumes -**[World Editors](../worlds)** +**[World Editors](../worlds/index.md)** - Spacer - the original world editor for ZenGin, ships with the MDK - [Union Gothic World Editor](https://worldofplayers.ru/threads/42322/) - Saturas' world editor, supports new object classes created with Union diff --git a/docs/zengin/tools/zSpy.md b/docs/zengin/tools/zSpy.md new file mode 100644 index 0000000000..24b0bc05f8 --- /dev/null +++ b/docs/zengin/tools/zSpy.md @@ -0,0 +1,121 @@ +# zSpy +**zSpy** is a debugging tool that displays most of the operations performed by the engine during the Gothic or Spacer running. + +??? example "Example image of running zSpy" + ![zSpy](../../assets/images/zSpy.png) + +!!! 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. + +## Log Level +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. + +## Output +The zSpy issues its reports in the following form: + +``` +Time Type Priority User Message ... +00:21 Info: 3 B: GOTHIC: Exiting game ... .... +``` + +### Time +Time elapsed since the start of Gothic.exe + +### Type +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. + +### Priority +Priority level of the message. Messages with lower priority (higher number) can be disabled. See [log level](#log-level). + +### User +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 + +### Message +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. + +## Configuration +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. + + +## Console commands +List of console commands related with zSpy. +!!! Note + The list is work in progress. Console commands needs a separate article or section. + +### `zerr level` +Sets a [level of logging](#log-level). +``` +zerr level <#> +``` + +- `<#>` - max message priority. See [log level](#log-level). + +### `zerr searchspy` +Links zSpy with Gothic. Useful when you run zSpy when the game is already running. +``` +zerr searchspy +``` + +### `zerr authors` +Sets a filter to display only messages of one author. +``` +zerr authors +``` + +- `` - One of the letters listed [here](#user). + +### `zerr rem` +Includes a remark into the log. +``` +zerr rem +``` +Looks like that: + +``` +00:46 Info: 3 B: OPT: Blood-Details: Value=2 .... +00:57 --------------- +00:57 --------------- +01:01 Info: 3 B: GMAN: Leaving Menu-Section .... +``` + +### `zerr status` +Displays a current status of zSpy in the console. +``` +zerr status +``` + diff --git a/docs/zengin/union/index.md b/docs/zengin/union/index.md index 992b7229d0..187060249c 100644 --- a/docs/zengin/union/index.md +++ b/docs/zengin/union/index.md @@ -6,7 +6,7 @@ Union plugins are shipped in the form of a `.dll` library. This library contains ## Union SDK & Gothic API 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 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. +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. ## PATCH file format 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. diff --git a/docs/zengin/union/plugins/zbassmusic.md b/docs/zengin/union/plugins/zbassmusic.md new file mode 100644 index 0000000000..9484f06cf8 --- /dev/null +++ b/docs/zengin/union/plugins/zbassmusic.md @@ -0,0 +1,19 @@ +# zBassMusic +zBassMusic is a modern music system for Gothic I and Gothic II NotR based on [BASS Audio Library](https://www.un4seen.com/) made by [Silver Ore Team](https://github.com/Silver-Ore-Team). It replaces the old DirectMusic system to let the modders create music for Gothic as regular audio files instead of DirectMusic format. + +!!! Info + For the plugin documentation, visit the [github site](https://github.com/Silver-Ore-Team/zBassMusic) of a project. The documentation is build into the code. + +| Contacts || +|:---------| :--- | +| Authors | [:material-badge-account-horizontal: Silver Ore Team](https://github.com/Silver-Ore-Team) - [tehe](https://github.com/piotrmacha) | +| GitHub | [:material-github: zBassMusic](https://github.com/Silver-Ore-Team/zBassMusic)| +| Discord | [:simple-discord: Gothic Modding Community server](https://discord.gg/mCpS5b5SUY) | + +## Features + +- Music playback with modern audio formats like WAV, MP3, OGG +- Out-of-the-box support for existing C_MUSICTHEME instances +- Scriptable interface to take full control of music scheduling +- Loading music files from VDFS volumes (excluding .sgt) +- Backwards compatibility with DirectMusic .sgt files diff --git a/docs/zengin/union/sdk/.pages b/docs/zengin/union/sdk/.pages new file mode 100644 index 0000000000..c85a6fae7b --- /dev/null +++ b/docs/zengin/union/sdk/.pages @@ -0,0 +1,4 @@ +title: Union SDK +nav: + - ... | getting_started*.md + - ... \ No newline at end of file diff --git a/docs/zengin/union/sdk/events.md b/docs/zengin/union/sdk/events.md new file mode 100644 index 0000000000..95fefb19cb --- /dev/null +++ b/docs/zengin/union/sdk/events.md @@ -0,0 +1,192 @@ +# Game Events +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. + +## Events + +### Initialization + +#### Game_Entry +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. +```cpp +void Game_Entry() { + +} +``` + +#### Game_DefineExternals +Executes before the Daedalus parser starts loading scripts. It's meant to define [custom external functions](externals.md). +```cpp +void Game_DefineExternals() { + +} +``` + +#### Game_Init +Executes right after DAT files are loaded and just before the main menu shows up. +```cpp +void Game_Init() { + +} +``` + + +### Level Change + +#### Game_LoadBegin +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. + +```cpp +void LoadBegin() { + +} + +// When player clicks "New Game" +void Game_LoadBegin_NewGame() { + LoadBegin(); +} + +// When player loads a saved game +void Game_LoadBegin_SaveGame() { + LoadBegin(); +} + +// When player changes ZEN by a trigger +void Game_LoadBegin_ChangeLevel() { + LoadBegin(); +} +``` + +#### Game_LoadEnd +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. + +```cpp +void LoadEnd() { + +} + +// When player clicks "New Game" +void Game_LoadEnd_NewGame() { + LoadEnd(); +} + +// When player loads a saved game +void Game_LoadEnd_SaveGame() { + LoadEnd(); +} + +// When player changes ZEN by a trigger +void Game_LoadEnd_ChangeLevel() { + LoadEnd(); +} +``` + +#### Game_LoadBegin_Trigger +Executes when the player enters a trigger that initiates ZEN change. + +```cpp +void Game_LoadBegin_Trigger() { + +} +``` + +#### Game_LoadEnd_Trigger +Executes after the player has entered a trigger that initiates ZEN change. + +```cpp +void Game_LoadEnd_Trigger() { + +} +``` + +#### Game_ApplyOptions +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. +```cpp +void Game_ApplyOptions() { + +} +``` + +### Game Loop + +#### Game_PreLoop +Executes at the start of every frame. + +```cpp +void Game_PreLoop() { + +} +``` + +#### Game_Loop +Executes at every frame. + +```cpp +void Game_Loop() { + +} +``` + +#### Game_PostLoop +Executes at the end of every frame. + +```cpp +void Game_PostLoop() { + +} +``` + +#### Game_MenuLoop +Executes at every frame when the game menu is active. + +```cpp +void Game_MenuLoop() { + +} +``` + +#### Game_SaveBegin +Executes when the player started saving a game. + +```cpp +void Game_SaveBegin() { + +} +``` + +#### Game_SaveEnd +Executes when the game save finishes. + +```cpp +void Game_SaveEnd() { + +} +``` + +#### Game_Pause +Executes when the player opens the in-game menu. + +```cpp +void Game_Pause() { + +} +``` + +#### Game_Unpause +Executes when the player leaves the in-game menu and also when the player loads a saved game. + +```cpp +void Game_Unpause() { + +} +``` + +### Shutdown + +#### Game_Exit +Executes when the player exits the game. + +```cpp +void Game_Exit() { + +} +``` \ No newline at end of file diff --git a/docs/zengin/union/sdk/externals.md b/docs/zengin/union/sdk/externals.md new file mode 100644 index 0000000000..09fe65f096 --- /dev/null +++ b/docs/zengin/union/sdk/externals.md @@ -0,0 +1,82 @@ +# Externals +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. + +```cpp +extern zCParser* parser; +extern zCParser*& parserSoundFX; +extern zCParser*& parserParticleFX; +extern zCParser*& parserVisualFX; +extern zCParser*& parserCamera; +extern zCParser*& parserMenu; +extern zCParser*& parserMusic; +``` + +## Creating custom external +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. +```dae +func string AddNumbers(var int FirstArgument, var int SecondArgument, var string ThirdArgument) {} +``` + +### Function handler +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. + +```cpp +// __cdecl is optional because it's the default calling convention +int __cdecl AddNumbers_External() +{ + // Declare arguments + int FirstArgument; + int SecondArgument; + zSTRING ThirdArgument; + + // Pop arguments from the stack **IN REVERSE ORDER** + parser->GetParameter(ThirdArgument); + parser->GetParameter(SecondArgument); + parser->GetParameter(FirstArgument); + + // Execute function logic + int result = FirstArgument + SecondArgument; + zSTRING output = ThirdArgument + zSTRING(result); + + // Push return value + parser->SetReturn(output); + + // Return value is ignored, so 0 or 1 is fine. + return 0; +} +``` + +### Register external +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 + +```cpp +void Game_DefineExternals() { + parser->DefineExternal("AddNumbers", AddNumbers_External, zPAR_TYPE_STRING, zPAR_TYPE_INT, zPAR_TYPE_INT, zPAR_TYPE_STRING, zPAR_TYPE_VOID); +} +``` + +Available types are defined by an enum: +```cpp +enum { + zPAR_TYPE_VOID, + zPAR_TYPE_FLOAT, + zPAR_TYPE_INT, + zPAR_TYPE_STRING, + zPAR_TYPE_CLASS, + zPAR_TYPE_FUNC, + zPAR_TYPE_PROTOTYPE, + zPAR_TYPE_INSTANCE +}; +``` \ No newline at end of file diff --git a/docs/zengin/union/sdk/getting_started.md b/docs/zengin/union/sdk/getting_started.md new file mode 100644 index 0000000000..25262ef68b --- /dev/null +++ b/docs/zengin/union/sdk/getting_started.md @@ -0,0 +1,138 @@ +# Getting Started + +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](index.md). + +## Creating Union plugin + +### Create a Visual Studio project + +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. + +#### File Structure + +| Folder / File | Description | +|----------------|-------------------------------------------| +| **Engine SDK/** | 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 SDK/User API/** | 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](hooks.md). | +| **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](events.md). | + +#### Build Configuration +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. + +#### Project Configuration + +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 `/System/Autorun` where `` 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 +```ini +[PLUGIN] +# Plugin file names without .dll +PluginList = MyPlugin +``` + +### Build the plugin +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: + +```cpp +void Game_Init() { + const CPlugin* myPlugin = CPlugin::GetCurrentPlugin(); + + CStringA gothicVersion; + switch (Union.GetEngineVersion()) { + case Engine_G1: gothicVersion = "Gothic I"; + case Engine_G1A: gothicVersion = "Gothic Sequel"; + case Engine_G2: gothicVersion = "Gothic II"; + case Engine_G2A: gothicVersion = "Gothic II NoTR"; + } + + CStringA message = "Plugin: " + myPlugin->GetName() + "\n"; + message = message + "Union Version: " + Union.GetUnionVersion().ToString() + "\n"; + message = message + "Gothic Version: " + gothicVersion; + + Message::Info(message, "Hello World"); +} +``` + +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 `/System/Autorun/MyPlugin.dll`. When we launch the game, a MessageBox should appear right before the main menu: +![Union SDK MessageBox](../../../assets/images/union_sdk_getting_started_messagebox.png){ style='min-width: 0;' } + +#### Couldn't build the plugin? +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`. + +## Debugging +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. + +### Visual Studio Debugger +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. + +### Print Debugging +Printing to some output is probably the simplest form of debugging and Union provides us with several choices. + +#### Logging to zSPY +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. +```cpp +zerr->Message("X: MyPlugin: message to zSPY"); +``` + +#### Logging to Union console +Union console needs to be enabled inside `SystemPack.ini` first: +```ini +[CORE] +ShowDebugWindow = true +``` +Then we can use a global `cmd` object behaving like C++ `std::cout` to log into the Union console: +```cpp +cmd << "message to Union console"; +``` + +#### Logging to Visual Studio +Visual Studio can also receive logs from our plugin using: +```cpp +OutputDebugString("message to Visual Studio"); +``` +This method works only when we have a debugger attached, so it's not recommended for general logging. diff --git a/docs/zengin/union/sdk/hooks.md b/docs/zengin/union/sdk/hooks.md new file mode 100644 index 0000000000..7b7948b01f --- /dev/null +++ b/docs/zengin/union/sdk/hooks.md @@ -0,0 +1,124 @@ +# Hooks +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`. + +## Intercepting functions +To declare a hook we can use `CInvoke` class or `HOOK AS` macros. +```cpp +CInvoke Ivk_HookName(orignal_function_address, our_interceptor_function, hook_flags); + +HOOK Ivk_HookName AS(orignal_function_address, our_interceptor_function, hook_flags); +``` + +### Regular functions +Regular functions are the functions declared outside of classes. +```cpp +// 0x0042C450 int __cdecl Apply_Options_Video(void) + +// Forward declaration +int Apply_Options_Video(); + +// Hook declaration +CInvoke Ivk_Apply_Options_Video(0x0042C450, &Apply_Options_Video); +// Equivalent: +// HOOK Ivk_Apply_Options_Video AS(0x0042C450, &Apply_Options_Video); + +// Implementation of interceptor +int Apply_Options_Video() { + Message::Info("Before original Apply_Options_Video()"); + + // Original function can be called using CInvoke pointer. + int result = Ivk_Apply_Options_Video(); + + Message::Info("After original Apply_Options_Video()"); + + return result; +} +``` + +### Member function +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. + +#### Option #1 - Regular function +```cpp +// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &) + +// Forward declaration +int __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context); + +// Hook declaration +CInvoke Ivk_zCVob_Render(0x006015D0, &zCVob_Render); +// Equivalent: +// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob_Render); + +// Implementation of interceptor as regular function +// Notice the first argument that's a pointer to class instance (this) +int __fastcall zCVob_Render(zCVob* _this, zTRenderContext& context) { + if(_this == player) { + screen->PrintCX(1000, "Rendering a player zCVob"); + } + + // Call original method + return Ivk_zCVob_Render(_this, context); +} +``` + +#### Option #2 - User API +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`: +```cpp +// Supported with union (c) 2020 Union team + +// User API for zCVob +// Add your methods here + +int RenderUnion(zTRenderContext& context); +``` + +Then we can declare the hook pointing to our member method: +```cpp +// 0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext &) + +// Hook declaration +CInvoke Ivk_zCVob_Render(0x006015D0, &zCVob::RenderUnion); +// Equivalent: +// HOOK Ivk_zCVob_Render AS(0x006015D0, &zCVob::RenderUnion); + +// Implementation of interceptor method +int zCVob::RenderUnion(zTRenderContext& context) { + if(this == player) { + screen->PrintCX(1000, "Rendering a player zCVob"); + } + + // Call original method + return Ivk_zCVob_Render(this, context); +} +``` + +## Hook flags +In the third argument of `CInvoke` we can provide hook flags. The default value is `IVK_AUTO`. + +```cpp +enum EInterMode +{ + // Hook will not intercept the function. + IVK_DISABLED = 1 << 1, + + // Normal hook. If other hook is already defined for the same address, an error pops up. + IVK_NORMAL = 1 << 2, + + // Hook will automatically create an interception tree to allow multiple hooks for the same address. + IVK_AUTO = 1 << 3, + + // Overrides any hook defined for the same address before. + IVK_REDEFINE = 1 << 4, + + // Makes it impossible to override or disable the hook. + // It should be used only in very specific cases. + IVK_PROTECTED = 1 << 5, + + // Same as IVK_DISABLED + IVK_READONLY = IVK_DISABLED +}; +``` + +## Credits +Examples are taken from the Union lessons in Russian created by Gratt on [worldofplayers.ru/threads/41490/](https://worldofplayers.ru/threads/41490/) diff --git a/docs/zengin/union/sdk/index.md b/docs/zengin/union/sdk/index.md new file mode 100644 index 0000000000..fe64a5a0d4 --- /dev/null +++ b/docs/zengin/union/sdk/index.md @@ -0,0 +1,14 @@ +# Union SDK +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. + +## Requirements +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/](https://visualstudio.microsoft.com/vs/) +* NET Framework 4.7.2 - [https://dotnet.microsoft.com/download/dotnet-framework/net472](https://dotnet.microsoft.com/download/dotnet-framework/net472) +* Visual C++ 2010 - [https://www.microsoft.com/download/details.aspx?id=26999](https://www.microsoft.com/download/details.aspx?id=26999) + +## Resource Manager +The official installation of Union SDK is provided through [Resource Manager](https://worldofplayers.ru/threads/41415/). After the installation, Visual Studio will have a new project template "Union Plugin 1.0" that creates a basic Union plugin project. diff --git a/docs/zengin/worlds/Classes/zCVob.md b/docs/zengin/worlds/Classes/zCVob.md new file mode 100644 index 0000000000..632380dd8f --- /dev/null +++ b/docs/zengin/worlds/Classes/zCVob.md @@ -0,0 +1,250 @@ +# zCVob + +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. + +## Class members +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](../spacer.md). On the other hand the **Vob** properties can only be changed by the Objects context menu in [Spacer](../spacer.md). + +=== "G1" + + - zCVob + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + - Internals + {: style="list-style-image: url('/gmc/assets/icons/spacer-folder.png');"} + - [pack](#pack) = 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-int.png');"} + - [presetName](#presetname) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [bbox3DWS](#bbox3dws) = 0 0 0 0 0 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-misc.png');"} + - [trafoOSToWSRot](#trafoostowsrot) = 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-misc.png');"} + - [trafoOSToWSPos](#trafoostowspos) = 0 0 200 + {: style="list-style-image: url('/gmc/assets/icons/spacer-vec.png');"} + - Vob + {: style="list-style-image: url('/gmc/assets/icons/spacer-folder.png');"} + - [vobName](#vobname) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [visual](#visual) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [showVisual](#showvisual) = TRUE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [visualCamAlign](#visualcamalign) = NONE + {: style="list-style-image: url('/gmc/assets/icons/spacer-enum.png');"} + - [CdStatic](#cdstatic) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [CdDyn](#cddyn) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [staticVob](#staticvob) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [dynShadow](#dynshadow) = DS_NONE + {: style="list-style-image: url('/gmc/assets/icons/spacer-enum.png');"} + - visual = NULL + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + - ai = NULL + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + +=== "G2A" + + - zCVob + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + - Internals + {: style="list-style-image: url('/gmc/assets/icons/spacer-folder.png');"} + - [pack](#pack) = 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-int.png');"} + - [presetName](#presetname) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [bbox3DWS](#bbox3dws) = 0 0 0 0 0 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-misc.png');"} + - [trafoOSToWSRot](#trafoostowsrot) = 0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-misc.png');"} + - [trafoOSToWSPos](#trafoostowspos) = 0 0 200 + {: style="list-style-image: url('/gmc/assets/icons/spacer-vec.png');"} + - Vob + {: style="list-style-image: url('/gmc/assets/icons/spacer-folder.png');"} + - [vobName](#vobname) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [visual](#visual) = "" + {: style="list-style-image: url('/gmc/assets/icons/spacer-string.png');"} + - [showVisual](#showvisual) = TRUE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [visualCamAlign](#visualcamalign) = NONE + {: style="list-style-image: url('/gmc/assets/icons/spacer-enum.png');"} + - [visualAniMode](#visualanimode) = NONE + {: style="list-style-image: url('/gmc/assets/icons/spacer-enum.png');"} + - [visualAniModeStrength](#visualanimodestrength) = 0.0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-float.png');"} + - [vobFarClipZScale](#vobfarclipzscale) = 1.0 + {: style="list-style-image: url('/gmc/assets/icons/spacer-float.png');"} + - [CdStatic](#cdstatic) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [CdDyn](#cddyn) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [staticVob](#staticvob) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - [dynShadow](#dynshadow) = DS_NONE + {: style="list-style-image: url('/gmc/assets/icons/spacer-enum.png');"} + - [zbias](#zbias) = 1 + {: style="list-style-image: url('/gmc/assets/icons/spacer-int.png');"} + - [isAmbient](#isambient) = FALSE + {: style="list-style-image: url('/gmc/assets/icons/spacer-bool.png');"} + - visual = NULL + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + - ai = NULL + {: style="list-style-image: url('/gmc/assets/icons/spacer-class.png');"} + + + +## Class member overview + +### pack +Internal property which indicates how the data associated with this virtual object is stored. + +### presetName +The name of the template that was used to create this virtual object. + +### bbox3DWS +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](#cdstatic) and [cdDyn](#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. + +### trafoOSToWSRot +The rotation of this virtual object in world space, represented by a 3x3 rotation matrix. + + +### trafoOSToWSPos +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](../spacer.md#viewport-controls) in spacer. + +### vobName +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. +### visual +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 + + +### showVisual +Indicates whether this object should display its visual. + +**Accepted values:** + +- **TRUE** - Display. +- **FALSE** - Do not display. + + +### visualCamAlign +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. + +### visualAniMode +Wind simulation option. Used in conjunction with the [visualAniModeStrength](#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). + +### visualAniModeStrength +Wind power animation multiplier. Small values such as `0.001` are typically used. Used in conjunction with the [visualAniMode](#visualanimode) parameter. + +!!! Warning + This option is only available in Gothic II (Spacer2). + +### vobFarClipZScale +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). + +### CdStatic +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 “refuse” 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. + +### CdDyn +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. + + +### staticVob +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. + +### dynShadow +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. + +### zbias +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). + +### isAmbient +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). + +[^1]: + Heavily inspired by the zCVob article at [gothic-library](http://www.gothic-library.ru/publ/class_zcvob/1-1-0-467). + +[^2]: + Corrected with information found in [ZenKit ZenGin Reference](https://zk.gothickit.dev/engine/objects/zCVob/). diff --git a/docs/zengin/worlds/spacer.md b/docs/zengin/worlds/spacer.md index 7975c052ba..5287809f08 100644 --- a/docs/zengin/worlds/spacer.md +++ b/docs/zengin/worlds/spacer.md @@ -94,7 +94,7 @@ This section covers some of the basic things done in the editor. - 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](https://dziejekhorinis.org/dev/vobbilder/). The UI on the website is in Polish but it's simple enough to not matter. + You can use the VOB Bilder tool to comfortably browse model images and names. An online version is currently available [here](https://vobbilder.dziejekhorinis.org/vobbilder/). 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. @@ -103,28 +103,7 @@ This section covers some of the basic things done in the editor. ### Common VOB settings -VOB settings vary depending on what the VOB type is. They all have common parameters of the base VOB class though: - -- vobName: an identifier shown in the editor and sometimes used in scripts. With some VOB types it's important to set this; for example waypoints and freepoints. -- visual: the mesh of the VOB -- showVisual: as the name suggests. Unknown usage. -- visualCamAlign: Unknown usage, possibly related to cutscenes. -- visualAniMode: Wind sway animation setting. -- visualAniModeStrength: a multiplier for the animation; small values such as `0.001` are typically used. -- vobFarClipZScale: a multiplier for the occlusion culling distance. Almost always left as 1, but it can be used to stop models from appearing from thin air in plain sight; e.g. a VOB of a hut which can be seen from afar might benefit from increasing this distance. The effects of this are visible in the editor. -- cdStatic: determines if the VOB will collide with the world mesh and other VOBs with `cdStatic` on. This is mostly used to help with placing objects in the editor, e.g. furniture. -- cdDyn: determines if the VOB will collide with dynamic objects (NPCs, items, etc.). This basically determines if the object has collision during gameplay. - -!!! warning - Both collision settings affect your ability to move VOBs. This can be either useful or disruptive depending on what you want to do. For example, if you want to clip a mesh with another one, you will need to disable collision and re-enable it after putting it in place. - -- staticVob: determines if the VOB is taken into consideration in static lighting calculations. Usually enabled in decorative VOBs, but some of the interactive ones have it disabled. -- dynShadow: seems to determine if the object will cast a shadow when affected by dynamic light (e.g. torches). -- zbias: Usage unknown. -- isAmbient: Usage unknown. - -!!! tip - One of the best ways of learning how to set up various VOBs is opening one of the original maps and checking the type and configuration of the related VOBs. Some things will require scripting to accomplish, however. +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](Classes/zCVob.md). ## Issues diff --git a/mkdocs.yml b/mkdocs.yml index a774cc7c78..ae946e0038 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,16 +1,22 @@ site_name: Gothic Modding Community -site_url: https://gothic-modding-community.github.io/gmc/ +site_url: !ENV [GMC_DEV_URL, 'https://gothic-modding-community.github.io/gmc/'] +site_description: 'Gothic Modding Community is a collection of helpful resources for modding Gothic and Risen games.' repo_name: Gothic-Modding-Community/gmc repo_url: https://github.com/Gothic-Modding-Community/gmc/ edit_uri: edit/main/docs/ watch: - - overrides + - overrides/assets + - overrides/.snippets + - overrides/main.html hooks: + - overrides/.hooks/theme_overrides_manager.py - overrides/.hooks/language_flags.py - overrides/.hooks/git_redirects.py + - overrides/.hooks/all_plugin_patch.py + - overrides/.hooks/preferences.py theme: name: material @@ -47,6 +53,7 @@ theme: - content.code.copy - content.action.edit - content.action.view + - content.tooltips extra_css: - assets/stylesheets/extra.css @@ -58,10 +65,10 @@ extra: social: - icon: fontawesome/brands/discord link: https://discord.gg/mCpS5b5SUY - name: Gothic Modding Comunity Discord Server + name: Gothic Modding Community Discord Server - icon: fontawesome/brands/github link: https://github.com/Gothic-Modding-Community/gmc - name: Gothic Modding Comunity Github repository + name: Gothic Modding Community GitHub repository @@ -75,13 +82,14 @@ markdown_extensions: - pymdownx.caret - pymdownx.details - pymdownx.highlight: - use_pygments: !ENV [GMC_ENABLE_ON_PUBLISH, False] + use_pygments: true linenums: true anchor_linenums: true # This sets the same ID for the and tags, # it's required for the links to work and to allow highlighting via JavaScript line_anchors: example line_spans: example + pygments_lang_class: true - pymdownx.inlinehilite - pymdownx.snippets: base_path: ['./overrides/.snippets/'] @@ -92,8 +100,8 @@ markdown_extensions: - footnotes - attr_list - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg - pymdownx.smartsymbols - pymdownx.tabbed: alternate_style: true @@ -125,59 +133,64 @@ plugins: js_files: - assets/javascripts/extra.js - i18n: - default_language: !ENV [GMC_DEFAULT_LANG, en] - default_language_only: !ENV [GMC_ONLY_DEFAULT_LANG, False] + build_only_locale: !ENV [GMC_DEV_LOCALE] + docs_structure: suffix languages: - en: - name: en - English - # Disable the /en/ path, a duplicate of the `default_language` build. - build: false - pl: - name: pl - Polski + - name: en - English + locale: en + default: true build: true - cs: - name: cs - Čeština - build: true - material_alternate: true - # Only 1 global scope, if 2 nav elements are named the same, input translation only once. - # Translate only the section/directory titles, page titles should be in the meta header of the `.md` file. - nav_translations: - en: - Afsp: AFSP - Anims: Animations - Contribute: How To Contribute - Daedalus tools: Daedalus - General info: General information - Genome: Genome (G3/R1) - Lego: LeGo - Vdfs tools: VDFS - Zengin: ZenGin (G1/G2) - Zgamepad: zGamePad - Zparserextender: zParserExtender - pl: - Anims: Animacje - Applications: Zastosowania - Classes: Klasy - Contribute: Jak Się Udzielić - Examples: Przykłady - Extensions: Rozszerzenia - Functions: Funkcje - General info: Informacje ogólne - Home: Strona Główna - Plugins: Wtyczki - Scripts: Skrypty - Syntax extensions: Rozszerzenia składni - Tools: Narzędzia - Tutorials: Poradniki - Various: Różne + nav_translations: + Afsp: AFSP + Anims: Animations + Contribute: How To Contribute + Daedalus tools: Daedalus + General info: General information + Genome: Genome (G3/R1) + Lego: LeGo + Vdfs tools: VDFS + Zengin: ZenGin (G1/G2) + Zgamepad: zGamePad + Zparserextender: zParserExtender + - name: pl - Polski + locale: pl + build: !ENV [GMC_ENABLE_ON_PUBLISH, GMC_BUILD_ALTERNATES, False] + site_description: 'Gothic Modding Community to zbiór pomocnych materiałów do modowania gier Gothic i Risen.' + nav_translations: + Anims: Animacje + Applications: Zastosowania + Classes: Klasy + Contribute: Jak Się Udzielić + Examples: Przykłady + Extenders: Extendery + Extensions: Rozszerzenia + Functions: Funkcje + General info: Informacje ogólne + Home: Strona Główna + Plugins: Pluginy + Scripts: Skrypty + Sound: Dźwięk + Standalone: Samodzielne + Syntax extensions: Rozszerzenia składni + Tools: Narzędzia + Tutorials: Poradniki + Various: Różne + Worlds: Światy + - name: cs - Čeština + locale: cs + build: !ENV [GMC_ENABLE_ON_PUBLISH, GMC_BUILD_ALTERNATES, False] + site_description: 'Dokumentace, návody a články zaměřené na modování her Gothic a Risen.' - git-revision-date-localized: enabled: !ENV [GMC_ENABLE_ON_PUBLISH, False] type: iso_datetime timezone: Europe/Warsaw exclude: - index*.md + - preferences*.md - genome/index*.md - zengin/index*.md - redirects: # Empty dict to fill with the `meta_redirects.py` hook. - redirect_maps: {} \ No newline at end of file + redirect_maps: {} + - social: + enabled: !ENV [GMC_ENABLE_ON_PUBLISH, False] \ No newline at end of file diff --git a/overrides/.hooks/all_plugin_patch.py b/overrides/.hooks/all_plugin_patch.py new file mode 100644 index 0000000000..c6a64451e2 --- /dev/null +++ b/overrides/.hooks/all_plugin_patch.py @@ -0,0 +1,283 @@ +"""MkDocs hook, which patches different plugins and modules used within Gothic Modding Community. + +Social Plugin (from the Material theme) +- The hook fixes a crash when using theme.font.code without theme.font.text. +- The hook overrides the `theme.logo` file lookup to use the custom_dir instead of the docs_dir. +- The hook does not override `theme.logo.icon` file lookup. +- The hook overrides the `on_page_markdown` function to make it compatible with the i18n plugin + +Pygments Lexers (used to highlight code) +- The hook decorates the pygments.lexers.get_lexer_by_name function, + adding cache for custom lexers, like the Gothic Lexer used in GMC + +i18n Plugin (mkdocs-static-i18n) +- The hook creates redirects for all built alternate languages using the mkdocs-redirects plugin +- The hook merges nav_translations of alternate languages with the default language + +Search Plugin (from the Material theme) +- The hook separates page.meta.title from page.markdown.title. + In turn the result heading should use the page.markdown.title. + +MIT Licence 2023 Kamil Krzyśków (HRY) +""" +import logging +from copy import deepcopy +from pathlib import Path +from typing import Optional + +from mkdocs import plugins +from mkdocs.config import Config +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import PrefixedLogger +from mkdocs.utils import get_markdown_title +from pygments import lexers +from pymdownx import highlight + + +@plugins.event_priority(100) +def on_config(config: MkDocsConfig) -> Optional[Config]: + social_plugin = config.plugins.get("material/social") or config.plugins.get("social") + i18n_plugin = config.plugins.get("i18n") + redirects_plugin = config.plugins.get("redirects") + + has_been_patched = hasattr(config.extra, "all_plugin_patch") + + # these patches can be run multiple times + # as they are aware of multiple executions + if i18n_plugin and redirects_plugin: + process_i18n_redirects(has_been_patched, i18n_plugin, redirects_plugin) + + # the rest of the patches only need to be applied once + # as they aren't aware of multiple executions + if has_been_patched: + return None + + LOG.info("Adding cache to custom lexers") + + highlight.get_lexer_by_name = patch_lexers_cache(lexers.get_lexer_by_name) + lexers.get_lexer_by_name = patch_lexers_cache(lexers.get_lexer_by_name) + + if social_plugin: + LOG.info("Fixing possible social card plugin crash") + social_plugin._load_font = patch_social_font_crash(social_plugin._load_font) + social_plugin._load_logo = patch_social_custom_dir(social_plugin._load_logo) + + if i18n_plugin: + process_i18n_nav_translations(i18n_plugin) + + return None + + +@plugins.event_priority(100) +def on_pre_build(config): + search_plugin = config.plugins.get("material/search") or config.plugins.get("search") + + if search_plugin and hasattr(search_plugin, "search_index"): + LOG.info("Separating page.title from page.meta.title in SearchIndex") + search_plugin.search_index.create_entry_for_section = patch_search_entry_title( + search_plugin.search_index.create_entry_for_section + ) + + +@plugins.event_priority(100) +def on_env(env, config, **_): + has_been_patched = hasattr(config.extra, "all_plugin_patch") + if not has_been_patched: + LOG.info("Enabling simple whitespace trimming in the Jinja2 environment") + + env.trim_blocks = True + env.lstrip_blocks = True + + return env + + +@plugins.event_priority(100) +def on_post_build(config) -> None: + has_been_patched = hasattr(config.extra, "all_plugin_patch") + if has_been_patched: + return + + social_plugin = config.plugins.get("material/social") or config.plugins.get("social") + i18n_plugin = config.plugins.get("i18n") + + if social_plugin and i18n_plugin: + LOG.info("Wrapping social plugin to prevent overlapping file names") + process_social_cards_i18n(config, social_plugin, i18n_plugin) + + config.extra.all_plugin_patch = True + + +class Mock: + ... + + +def patch_social_font_crash(func): + """Patch the theme["font"]["text"] crash""" + + def wrap_load_font(config): + theme = config.theme + if "font" in theme and "text" not in theme["font"]: + mock_config = Mock() + mock_config.theme = deepcopy(config.theme) + mock_config.theme["font"]["text"] = "Roboto" + return func(mock_config) + return func(config) + + return wrap_load_font + + +def patch_social_custom_dir(func): + """Patch support for paths in `custom_dir`""" + + def wrap_load_logo(config): + mock_config = Mock() + mock_config.theme = config.theme + mock_config.docs_dir = str(Path(config.docs_dir).parent / CUSTOM_DIR_PATH) + return func(mock_config) + + return wrap_load_logo + + +def patch_lexers_cache(func): + """Patch cache into the get_lexer_by_name function""" + + def wrap_get_lexer_by_name(alias, **options): + cached_class = LEXER_CLASS_CACHE.get(alias) + + if cached_class: + return cached_class(**options) + + lexer = func(alias, **options) + LEXER_CLASS_CACHE[alias] = lexer.__class__ + return lexer + + return wrap_get_lexer_by_name + + +def process_i18n_redirects(has_been_patched, i18n_plugin, redirects_plugin): + import mkdocs_redirects.plugin as module + + # clear the redirects_maps in the alternate builds, + # because everything is created in the default build + if has_been_patched: + redirects_plugin.config["redirect_maps"].clear() + return + + # assert API is available to change + if not hasattr(module, "write_html"): + LOG.warning("Current version of mkdocs-redirects plugin isn't compatible with the patch") + return + + LOG.info("Wrapping mkdocs-redirects to also create redirects for alternate languages") + + def write_html_decorator(func): + def write_html_wrapper(site_dir, old_path, new_path): + # write html for default build + func(site_dir, old_path, new_path) + # write html for each built alternate + for lang in i18n_plugin.config.languages: + if lang.build is True and lang.default is False: + func(site_dir, lang.link[1:] + old_path, new_path) + + return write_html_wrapper + + module.write_html = write_html_decorator(module.write_html) + + +def process_i18n_nav_translations(i18n_plugin): + for lang in i18n_plugin.config.languages: + if lang.default is True: + default_translations = lang.nav_translations or {} + + if not default_translations: + return + + LOG.info("Merging nav_translations of alternate languages with default") + + for lang in i18n_plugin.config.languages: + if lang.default is False and lang.build is True: + lang.nav_translations = {**default_translations, **(lang.nav_translations or {})} + + +def process_social_cards_i18n(config, social_plugin, i18n_plugin): + """ + The social plugin uses the page.file.src_path and page.file.src_uri + to generate both the card image filename and html meta tag url to that file. + To avoid overwriting the default language cards, when another language page + isn't translated it's required to wrap the plugin's on_page_markdown event + and provide the page object with replaced values + TODO The Insiders Social Plugin could behave differently, and the wrapper might not work + """ + + def on_page_markdown_decorator(func): + def on_page_markdown_wrapper(markdown, page, config, files): + src_path = Path(page.file.src_path) + + # if the source path has multiple suffixes it won't override the default language + if len(src_path.suffixes) > 1: + return func(markdown, page, config, files) + + src_uri = Path(page.file.src_uri) + + page.file.src_path = str( + src_path.parent / f"{src_path.stem}.{i18n_plugin.current_language}{src_path.suffix}" + ) + page.file.src_uri = ( + src_uri.parent / f"{src_uri.stem}.{i18n_plugin.current_language}{src_uri.suffix}" + ).as_posix() + + output = func(markdown, page, config, files) + + # restore the page object paths to initial state + page.file.src_path = str(src_path) + page.file.src_uri = src_uri.as_posix() + + return output + + return on_page_markdown_wrapper + + for i, event in enumerate(config.plugins.events["page_markdown"]): + if not hasattr(event, "__self__"): + continue + if event.__self__.__class__ is social_plugin.__class__: + config.plugins.events["page_markdown"][i] = on_page_markdown_decorator(event) + break + + +def patch_search_entry_title(func): + """ + Navigation / social card titles should be controlled separately in the page front matter. + Search result titles should be like the first h1 heading in the markdown content. + The search plugin implementation in the Material theme doesn't work like that, so + we patch it. + """ + + def wrap_create_entry_for_section(section, toc, url, page): + old_meta_title = page.meta.get("title") + old_page_title = page.title + page_markdown_title = get_markdown_title(page.markdown) + + page.meta["title"] = page_markdown_title + page.title = page_markdown_title + + result = func(section, toc, url, page) + + page.meta["title"] = old_meta_title + page.title = old_page_title + + return result + + return wrap_create_entry_for_section + + +CUSTOM_DIR_PATH = "overrides" +"""A relative path to the custom directory based from the `docs_dir` parent directory.""" + +HOOK_NAME: str = "all_plugin_patch" +"""Name of this hook. Used in logging.""" + +LEXER_CLASS_CACHE = {} +"""Lexer class cache dictionary for patch_lexers_cache""" + +LOG: PrefixedLogger = PrefixedLogger(HOOK_NAME, logging.getLogger(f"mkdocs.hooks.{HOOK_NAME}")) +"""Logger instance for this hook.""" diff --git a/overrides/.hooks/git_redirects.py b/overrides/.hooks/git_redirects.py index 82d80a7e74..97550784f8 100644 --- a/overrides/.hooks/git_redirects.py +++ b/overrides/.hooks/git_redirects.py @@ -4,10 +4,12 @@ by the `MAX_DATE` and `MAX_HASH` constants. It checks the diff between 2 adjacent commits and processes the diff items marked with the "R" (moved/renamed) status. -MIT Licence 2023 Kamil Krzyśków +MIT Licence 2023 Kamil Krzyśków (HRY) """ import datetime +import json import logging +import os from pathlib import Path from typing import Dict, Optional, Set @@ -19,6 +21,7 @@ GIT_MODULE = True from mkdocs.config import Config from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import PrefixedLogger # region Core Logic @@ -26,37 +29,99 @@ def on_config(config: MkDocsConfig) -> Optional[Config]: """Main function. Check the `redirects` plugin is present and fill the redirects mapping.""" + try: + hook_enabled = custom_getenv(HOOK_VAR, False) + except ValueError as err: + LOG.error(err) + return None + + if not hook_enabled: + LOG.info(f"{HOOK_VAR} is not set to True in the environment") + return None + if not GIT_MODULE: - LOG.warning(f"{HOOK_NAME}: The `GitPython` module is not installed") + LOG.warning("The `GitPython` module is not installed") return None if "redirects" not in config["plugins"]: - LOG.warning(f"{HOOK_NAME}: The `redirects` plugin is not in the config") + LOG.warning("The `redirects` plugin is not in the config") return None if "redirect_maps" not in config["plugins"]["redirects"].config: - LOG.warning(f"{HOOK_NAME}: The `redirects` plugin is not configured correctly") + LOG.warning("The `redirects` plugin is not configured correctly") return None - _add_redirects_based_on_git_history(config=config) + if config.extra.get("git_redirects_finished", False): + LOG.info("MkDocsConfig wasn't reset since last run, skipping run...") + return None + + try: + cache_enabled = custom_getenv(CACHE_VAR, False) + except ValueError as err: + LOG.error(err) + return None + + if cache_enabled: + CacheHelper.setup(config=config) + commit_hash = _add_redirects_based_on_git_history(config=config, cache_enabled=True) + if commit_hash is not None and commit_hash != CacheHelper.cache_obj["commit_hash"]: + CacheHelper.cache_obj["commit_hash"] = commit_hash + CacheHelper.save(config=config) + else: + _add_redirects_based_on_git_history(config=config) + + config.extra["git_redirects_finished"] = True return None -def _add_redirects_based_on_git_history(*, config: MkDocsConfig) -> None: +# Credit to https://stackoverflow.com/a/65407083 +def custom_getenv(name: str, default_value: bool = None): + positive: tuple[str] = ("true", "1") + negative: tuple[str] = ("false", "0") + value: str = os.getenv(name, None) + + if value is None: + if default_value is None: + raise ValueError(f"Variable '{name}' is not set and no default provided!") + else: + value = str(default_value) + + if value.lower() not in positive + negative: + raise ValueError(f"Invalid value '{value}' for variable '{name}'") + + return value.lower() in positive + + +def _add_redirects_based_on_git_history( + *, config: MkDocsConfig, cache_enabled: bool = False +) -> Optional[str]: """Process the Git history looking for rename actions.""" docs_dir: Path = Path(config.get("docs_dir")) - file_paths: Set[str] = {str(path) for path in docs_dir.glob("**/*.md")} docs_prefix: str = docs_dir.name + "/" project_root: Path = docs_dir.parent + repo = Repo(project_root) redirects: Dict[str, str] = config["plugins"]["redirects"].config["redirect_maps"] + if cache_enabled: + redirects.update(CacheHelper.cache_obj["redirects"]) + + if MAX_HASH and len(repo.commit(MAX_HASH).parents) > 1: + LOG.warning("Using a Merge commit revision for 'MAX_HASH' is not supported") + return None + + if cache_enabled and repo.head.commit.hexsha == CacheHelper.cache_obj["commit_hash"]: + LOG.info("HEAD commit already cached") + return None + + file_paths: Set[str] = {str(path) for path in docs_dir.glob("**/*.md")} + initial_len: int = len(redirects) - LOG.info(f"{HOOK_NAME}: Processing Git history...") + LOG.info(f"Processing Git history with{'' if cache_enabled else 'out'} cache...") - for commit in Repo(project_root).iter_commits(since=MAX_DATE, max_parents=1): + for commit in repo.iter_commits(since=MAX_DATE, max_parents=1): if not commit.parents: break @@ -67,7 +132,9 @@ def _add_redirects_based_on_git_history(*, config: MkDocsConfig) -> None: old_parts_len: int = len(old.split("/")[-1].split(".")) new_parts_len: int = len(new.split("/")[-1].split(".")) old_exists: bool = str(project_root / old) in file_paths - old_index_exists: bool = str(project_root / old.replace(".md", "/index.md")) in file_paths + old_index_exists: bool = ( + str(project_root / old.replace(".md", "/index.md")) in file_paths + ) type_md: bool = old.endswith(".md") and new.endswith(".md") inside_docs: bool = old.startswith(docs_prefix) and new.startswith(docs_prefix) @@ -91,25 +158,73 @@ def _add_redirects_based_on_git_history(*, config: MkDocsConfig) -> None: if old_inner not in redirects: redirects[old_inner] = new_inner else: - LOG.info(f"{HOOK_NAME}: '{old_inner}' already in redirects, keeping more recent one") + LOG.info(f"'{old_inner}' already in redirects, keeping more recent one") if commit.hexsha == MAX_HASH: break + if cache_enabled and commit.parents[0].hexsha == CacheHelper.cache_obj["commit_hash"]: + LOG.info("Reached cached commits") + break + len_diff: int = len(redirects) - initial_len if len_diff > 0: - LOG.info(f"{HOOK_NAME}: Created {len_diff} redirects") + LOG.info(f"Created {len_diff} redirects") + + if cache_enabled: + return repo.head.commit.hexsha + + +class CacheHelper: + """Class contains variables related to caching""" + + cache_dir: Optional[Path] = None + """Directory path to the plugin cache directory""" + + cache_file: Optional[Path] = None + """File path where the cached redirects will be saved""" + + cache_obj: Optional[Dict] = None + """Object, which will be saved to cache""" + + @classmethod + def setup(cls, *, config: MkDocsConfig) -> None: + cls.cache_dir = Path(config.get("docs_dir")).parent / CACHE_PATH + formatted_date: str = ( + MAX_DATE.isoformat().replace(":", "") if isinstance(MAX_DATE, datetime.datetime) else "" + ) + cls.cache_file = cls.cache_dir / f"{formatted_date}-{MAX_HASH}.json" + + if cls.cache_file.exists(): + cls.cache_obj = json.loads(cls.cache_file.read_text(encoding="utf8")) + else: + cls.cache_obj: Dict = {"commit_hash": "", "redirects": {}} + cls.cache_dir.mkdir(parents=True, exist_ok=True) + cls.cache_file.write_text(json.dumps(cls.cache_obj), encoding="utf8") + + @classmethod + def save(cls, *, config: MkDocsConfig) -> None: + cls.cache_obj["redirects"] = config["plugins"]["redirects"].config["redirect_maps"] + cls.cache_file.write_text(json.dumps(cls.cache_obj, indent=2), encoding="utf8") # endregion # region Constants +CACHE_VAR: str = "GMC_ENABLE_ON_PUBLISH" +"""Name of the environmental variable to enable caching.""" HOOK_NAME: str = "git_redirects" """Name of this hook. Used in logging.""" -LOG: logging.Logger = logging.getLogger(f"mkdocs.hooks.{HOOK_NAME}") +CACHE_PATH: str = f".cache/hooks/{HOOK_NAME}" +"""A relative path to the cache directory, based from the `config.docs_dir` parent directory.""" + +HOOK_VAR: str = "GMC_ENABLE_ON_PUBLISH" +"""Name of the environmental variable to enable the hook.""" + +LOG: PrefixedLogger = PrefixedLogger(HOOK_NAME, logging.getLogger(f"mkdocs.hooks.{HOOK_NAME}")) """Logger instance for this hook.""" # MAX_DATE: datetime.datetime = datetime.datetime.now() - datetime.timedelta(days=99) diff --git a/overrides/.hooks/language_flags.py b/overrides/.hooks/language_flags.py index 3008a4a801..266674f0f7 100644 --- a/overrides/.hooks/language_flags.py +++ b/overrides/.hooks/language_flags.py @@ -1,166 +1,44 @@ -"""MkDocs hook, which adds flag emojis to the language selector, works only with the Material theme. +"""MkDocs hook, which adds flag emojis to the language selector. +Works only with the Material theme, and requires the "theme_overrides_manager" hook. The hook dynamically on the fly modifies the "header.html" template of the Material theme before the build. -It restores the file after the build finishes. Works both with and without the "i18n" MkDocs plugin. +It uses the theme_overrides_manager hook to assure original file preservation. +Works both with and without the "i18n" MkDocs plugin. -MIT Licence 2023 Kamil Krzyśków +MIT Licence 2023 Kamil Krzyśków (HRY) Parts adapted from the translations.py hook https://github.com/squidfunk/mkdocs-material/blob/master/src/.overrides/hooks/translations.py and from the materialx.emoji and pymdownx.emoji modules. """ -import enum -import filecmp import logging -import shutil -import tempfile from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Tuple, Union, Set +from typing import Dict, Optional, Union -import jinja2 -import material -from mkdocs.config import Config +from jinja2 import Environment from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import PrefixedLogger from pymdownx import twemoji_db, util from pymdownx.emoji import TWEMOJI_SVG_CDN -# region Backup Management Class - - -class BackupManager: - """Helper class, which handles the backing up of files""" - - class BackupState(enum.IntEnum): - """Possible states for the backup process""" - - NONE: int = 10 - """None backups exist""" - - CREATED: int = 20 - """All backups exist""" - - backup_state: BackupState = BackupState.NONE - """Status of the backup process""" - - _confirmed_backups: List[Tuple[Path, Path]] = [] - """List of pairs of source and backup file paths""" - - sources: Set[Path] = set() - """List of source file paths""" - - def __init__(self): - raise NotImplementedError("This class should have no instances.") - - @classmethod - def create_backup(cls, *, config: MkDocsConfig) -> None: - """Creates backup files with ".backup" suffix within the same directory as the source file.""" - - for src in cls.sources: - if str(src) not in config["extra"][HOOK_NAMESPACE]["created_backups"]: - cls._confirmed_backups.append((src, Path(f"{src}.backup"))) - - backup_len: int = len(cls._confirmed_backups) - - if not cls.sources: - LOG.warning( - f"{HOOK_NAME}: No sources selected for backup. You might corrupt your installation" - ) - elif backup_len > 0: - LOG.info( - f'{HOOK_NAME}: Backing up {backup_len} file{"" if backup_len == 1 else "s"}...' - ) - elif backup_len == 0: - LOG.info(f"{HOOK_NAME}: Files already backed up") - - for src, backup in cls._confirmed_backups: - if backup.exists(): - LOG.info(f'{HOOK_NAME}: Found "{backup.name}" before creation, restoring...') - shutil.copy2(backup, src) - assert filecmp.cmp(backup, src, shallow=False) - continue - - shutil.copy2(src, backup) - assert filecmp.cmp(src, backup, shallow=False) - LOG.debug(f'{HOOK_NAME}: Created "{backup.name}"') - config["extra"][HOOK_NAMESPACE]["created_backups"].add(str(src)) - - if backup_len > 0: - cls.backup_state = cls.BackupState.CREATED - - @classmethod - def restore_backup(cls) -> None: - """Restores backup files and deletes them after""" - - # Clear sources set for the next creation - cls.sources.clear() - - if cls.backup_state != cls.BackupState.CREATED: - return - - backup_len: int = len(cls._confirmed_backups) - - LOG.info(f'{HOOK_NAME}: Restoring {backup_len} file{"" if backup_len == 1 else "s"}...') - for src, backup in cls._confirmed_backups: - if not backup.exists(): - LOG.error(f'{HOOK_NAME}: Backup "{backup.name}" doesn\'t exist') - continue - - shutil.copy2(backup, src) - assert filecmp.cmp(backup, src, shallow=False) - backup.unlink() - LOG.debug(f'{HOOK_NAME}: Restored "{src.name}"') - - # Clear backups list for the next creation - cls._confirmed_backups.clear() - cls.backup_state = cls.BackupState.NONE - - -# endregion - - # region Core Logic Events -def on_config(config: MkDocsConfig) -> Optional[Config]: - """Triggers just after the config loaded. Initialize the namespace to pass data between hooks.""" - - LOG.debug(f'{HOOK_NAME}: Running "on_config"') - - if "extra" in config and HOOK_NAMESPACE in config["extra"]: - registrant: str = config["extra"][HOOK_NAMESPACE]["registrant"] - LOG.info(f'{HOOK_NAME}: Using namespace registered by "{registrant}"') - return None - - if "extra" not in config: - config["extra"]: Dict[str, Any] = {} - - namespace: Dict[str, Any] = { - "registrant": HOOK_NAME, - "created_backups": set(), - } - - config["extra"][HOOK_NAMESPACE] = namespace - LOG.info(f'{HOOK_NAME}: Namespace "{HOOK_NAMESPACE}" registered') - - return None - - -def on_env(*_, config: MkDocsConfig, **__) -> Optional[jinja2.Environment]: +def on_env(*_, config: MkDocsConfig, **__) -> Optional[Environment]: """Main function. Triggers just before the build begins.""" - LOG.debug(f'{HOOK_NAME}: Running "on_env"') + LOG.debug('Running "on_env"') if not _is_runnable(config=config): return None - partials: Path = Path(material.__file__).parent / "partials" - header: Path = partials / "header.html" + import material - # Assign files to their processor functions - file_and_processors: List[Tuple[Path, Callable]] = [ - (header, _add_flags), - ] + partials: Path = Path(material.__file__).parent / "templates" / "partials" + header: Path = partials / "alternate.html" - _process_files(mapping=file_and_processors, config=config) + config.extra[HOOK_MANAGER].paths_with_processors.append((header, _add_flags)) + + LOG.info(f"Registered processors") return None @@ -168,141 +46,79 @@ def on_env(*_, config: MkDocsConfig, **__) -> Optional[jinja2.Environment]: def _is_runnable(*, config: MkDocsConfig) -> bool: """Make sure the hook should run.""" - if config["theme"]["name"] != "material": - LOG.info(f'{HOOK_NAME}: Only the "material" theme is supported') + if HOOK_MANAGER not in config["extra"]: + LOG.info(f'"{HOOK_MANAGER}" not detected') return False - if "extra" not in config or "alternate" not in config["extra"]: - LOG.info(f'{HOOK_NAME}: "extra.alternate" not detected') + if config.theme["name"] != "material": + LOG.info('Only the "material" theme is supported') + return False + + if "alternate" not in config["extra"]: + LOG.info('"extra.alternate" not detected') return False if len(config["extra"]["alternate"]) < 2: - LOG.info(f"{HOOK_NAME}: Not enough languages") + LOG.info(f"Not enough languages") return False return True -def _process_files(*, mapping: List[Tuple[Path, Callable]], config: MkDocsConfig) -> None: - """Create backups and call each processing function.""" - - # Fill out the set of source file paths - for src, _ in mapping: - BackupManager.sources.add(src) - - BackupManager.create_backup(config=config) - - # Invoke each function with the src Path and MkDocsConfig - for src, func in mapping: - func(partial=src, config=config) - - -def _add_flags(*, partial: Path, config: MkDocsConfig) -> None: +def _add_flags(*, partial: Path, config: MkDocsConfig, **__) -> None: """Process the "header.html" partial and add flags to the language selector template.""" # Configure the tokens tokens: Dict[str, str] = { - "START": "{% if config.extra.alternate %}", + "START": '
', "CONFIG": '{% set icon = config.theme.icon.alternate or "material/translate" %}', "SELECTOR": '{% include ".icons/" ~ icon ~ ".svg" %}', "LINK": "{{ alt.name }}", - "END": "{% endif %}", + "END": "
", } # A negative number means the same level as the START token. end_indent_level: int = -1 - # Open the file and load the section - with open(partial, encoding="utf8") as file: - loaded_content: str = file.read() + override_manager = config.extra[HOOK_MANAGER] - loaded_section: str = _load_section( - content=loaded_content, + loaded_section: str = override_manager.load_section( + partial=partial, tokens=tokens, end_level=end_indent_level, - file_name=partial.name, ) # Do not continue when section is not loaded if not loaded_section: return - # Do not continue when section is not valid (due to some update or another hook) - if not _is_section_valid(tokens=tokens, loaded_section=loaded_section, file_name=partial.name): - return - # Load all flags relevant to the current build flag_mapping: Dict[str, str] = { alt["lang"]: _flag_svg(alt["lang"]) for alt in config["extra"]["alternate"] } # Set the "flag_mapping" selector - selector: str = "config.theme.language" + # Choose different selector for the "i18n" plugin + selector: str = "i18n_page_locale" if "i18n" in config.plugins else "config.theme.language" - # Change selector for the "i18n" plugin - if "i18n" in config.plugins: - selector = "i18n_page_locale" - - # Modify the partial - with open(partial, "w", encoding="utf8") as file: - file.write( - loaded_content.replace( - loaded_section, - loaded_section.replace( - tokens["CONFIG"], "{% set flag_mapping = " + str(flag_mapping) + " %}" - ) - .replace(tokens["SELECTOR"], "{{ flag_mapping[" + selector + "] }}") - .replace( - tokens["LINK"], - "{{ flag_mapping[alt.lang] }} " - + '{{ alt.name | replace(alt.lang, "") | replace(" ", "") | replace("-", "") }}', - ), - ) + modified_section: str = ( + loaded_section.replace( + tokens["CONFIG"], "{% set flag_mapping = " + str(flag_mapping) + " %}" ) + .replace(tokens["SELECTOR"], "{{ flag_mapping[" + selector + "] }}") + .replace( + tokens["LINK"], + "{{ flag_mapping[alt.lang] }} " + + '{{ alt.name | replace(alt.lang, "") | replace(" ", "") | replace("-", "") }}', + ) + ) - LOG.debug(f'{HOOK_NAME}: Processed "{partial.name}".') - - -def _load_section(*, content: str, tokens: Dict[str, str], end_level: int, file_name: str) -> str: - """Load the section from the content""" - - lines: List[str] = [] - section_started: bool = False - section_ended: bool = False - - for line in content.split("\n"): - if tokens["START"] in line: - section_started = True - if end_level < 0: - end_level = len(line) - len(line.lstrip()) - - if section_started: - lines.append(line) - if tokens["END"] in line and (len(line) - len(line.lstrip())) == end_level: - section_ended = True - break - - if not section_ended or not section_started: - message: str = "started" if not section_started else "ended" - LOG.error(f'{HOOK_NAME}: Section in file "{file_name}" never {message}') - _write_log("\n".join(lines), f"{HOOK_NAME}_read_error.html") - return "" - - return "\n".join(lines) - - -def _is_section_valid(*, tokens: Dict[str, str], loaded_section: str, file_name: str) -> bool: - """Validate that the loaded section contains all tokens""" - - try: - for value in tokens.values(): - assert value in loaded_section - except AssertionError: - LOG.error(f'{HOOK_NAME}: Section mismatch in "{file_name}"') - _write_log(loaded_section, f"{HOOK_NAME}_mismatch.html") - return False + # Modify the partial + override_manager.save_section( + partial=partial, original_section=loaded_section, modified_section=modified_section + ) - return True + LOG.debug(f'Processed "{partial.name}".') def _flag_svg(alternate_lang: str) -> str: @@ -328,41 +144,8 @@ def _flag_svg(alternate_lang: str) -> str: return f'{alt}' -def _write_log(content: str, file_name: str) -> None: - """Write `content` to TEMP_DIR/`file_name`""" - crash_log = Path(tempfile.gettempdir()) / file_name - with open(crash_log, "w", encoding="utf8") as file: - file.write(content) - LOG.info(f'{HOOK_NAME}: File saved "{crash_log}"') - - # endregion -# region Closing Events - - -def on_build_error(*_, **__) -> None: - """Restores backup. Triggers when the build errors, safety measure if "on_shutdown" won't trigger.""" - - LOG.debug(f'{HOOK_NAME}: Running "on_build_error"') - BackupManager.restore_backup() - - -def on_post_build(*_, **__) -> None: - """Restores backup. Triggers when a build finishes.""" - - LOG.debug(f'{HOOK_NAME}: Running "on_post_build"') - BackupManager.restore_backup() - - -def on_shutdown(*_, **__) -> None: - """Restores backup. Triggers when MkDocs terminates.""" - - LOG.debug(f'{HOOK_NAME}: Running "on_shutdown"') - BackupManager.restore_backup() - - -# endregion # region Constants @@ -433,8 +216,8 @@ def on_shutdown(*_, **__) -> None: HOOK_NAME: str = "language_flags" """Name of this hook. Used in logging.""" -HOOK_NAMESPACE: str = "material_override_hooks" -"""Namespace of this hook. Used for storing data shared between hooks.""" +HOOK_MANAGER: str = "theme_overrides_manager" +"""Name of the hook manager. Used to access it in `config.extra`.""" INDEX: Dict[str, Union[str, Dict]] = { "name": "twemoji", @@ -445,7 +228,9 @@ def on_shutdown(*_, **__) -> None: # Adapted from # materialx.emoji -LOG: logging.Logger = logging.getLogger(f"mkdocs.hooks.{HOOK_NAME}") +LOG: PrefixedLogger = PrefixedLogger( + HOOK_NAME, logging.getLogger(f"mkdocs.hooks.theme_overrides.{HOOK_NAME}") +) """Logger instance for this hook.""" # endregion diff --git a/overrides/.hooks/preferences.py b/overrides/.hooks/preferences.py new file mode 100644 index 0000000000..021e13369c --- /dev/null +++ b/overrides/.hooks/preferences.py @@ -0,0 +1,38 @@ +"""Hook that manages the preferences.md page, primarily i18n dynamics. +""" +import re + +from mkdocs import plugins +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.structure.files import Files +from mkdocs.structure.pages import Page + + +@plugins.event_priority(100) +def on_page_markdown( + markdown: str, /, *, page: Page, config: MkDocsConfig, files: Files +) -> str | None: + if "preferences_i18n" not in page.meta: + return markdown + + default_lang_code: str = "en" + lang_code: str = ( + config.theme["language"] + if config.theme["language"] in page.meta["preferences_i18n"] + else default_lang_code + ) + current_i18n: dict[str, str] = { + **page.meta["preferences_i18n"][default_lang_code], + **page.meta["preferences_i18n"][lang_code], + } + tokens: list[str] = re.findall(r"\{\{.*?}}", markdown) + + for token in tokens: + short_token = token.lstrip("{{").rstrip("}}").strip() + markdown = markdown.replace(token, current_i18n[short_token]) + + # print(1, lang_code) + # print(2, current_i18n) + # print(3, tokens) + + return markdown diff --git a/overrides/.hooks/theme_overrides_manager.py b/overrides/.hooks/theme_overrides_manager.py new file mode 100644 index 0000000000..2b3e337631 --- /dev/null +++ b/overrides/.hooks/theme_overrides_manager.py @@ -0,0 +1,279 @@ +"""MkDocs hook, which adds a backup and restore cycle for files that will be overriden. + +On its own it is not that useful. It acts as the manager for other hooks. +It gathers all files from other hooks and triggers their functions. + +MIT Licence 2023 Kamil Krzyśków (HRY) +""" +import enum +import filecmp +import logging +import shutil +import tempfile +from pathlib import Path +from typing import Callable, Dict, List, Optional, Set, Tuple + +import jinja2 +from mkdocs import plugins +from mkdocs.config import Config +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import PrefixedLogger +from mkdocs.structure.files import Files + +# region Core Logic Events + + +@plugins.event_priority(100) +def on_config(config: MkDocsConfig) -> Optional[Config]: + """Triggers just after the config loaded. + + Initializes the ThemeOverridesManager class to pass data between hooks. + """ + + LOG.debug('Running "on_config"') + + ThemeOverridesManager.initialize() + config.extra[HOOK_NAME] = ThemeOverridesManager + + LOG.info("Theme overrides manager initialized") + + return None + + +@plugins.event_priority(-75) +def on_env( + env: jinja2.Environment, *, config: MkDocsConfig, files: Files +) -> Optional[jinja2.Environment]: + """Main function. Triggers just before the build begins.""" + + LOG.debug('Running "on_env"') + + if not ThemeOverridesManager.all_paths_exist(): + return None + + if not ThemeOverridesManager.paths_with_processors: + LOG.info("No file processors were registered") + return None + + ThemeOverridesManager.create_backup() + + # Invoke each function with all available parameters + for path, func in ThemeOverridesManager.paths_with_processors: + func(partial=path, env=env, config=config, files=files) + + return None + + +# endregion + +# region Closing Events + + +def on_build_error(*_, **__) -> None: + """Restores backup. Triggers when the build errors, safety measure if "on_shutdown" won't trigger.""" + + LOG.debug('Running "on_build_error"') + + ThemeOverridesManager.restore_backup() + + +def on_post_build(*_, **__) -> None: + """Restores backup. Triggers when a build finishes.""" + + LOG.debug('Running "on_post_build"') + + ThemeOverridesManager.restore_backup() + + +def on_shutdown(*_, **__) -> None: + """Restores backup. Triggers when MkDocs terminates.""" + + LOG.debug('Running "on_shutdown"') + + ThemeOverridesManager.restore_backup() + + +# endregion + + +# region Backup Management Class + + +class BackupState(enum.IntEnum): + """Possible states for the backup process""" + + NONE: int = 10 + """None backups exist""" + + CREATED: int = 20 + """All backups exist""" + + +class ThemeOverridesManager: + """Helper class, which handles the backing up of files""" + + def __init__(self): + raise NotImplementedError("This class should have no instances.") + + @classmethod + def initialize(cls): + cls.backup_state = BackupState.NONE + cls.sources = set() + cls.paths_with_processors = [] + + @classmethod + def all_paths_exist(cls) -> bool: + """Checks if the provided source paths exist""" + + result = True + + for src, _ in cls.paths_with_processors: + if not src.exists(): + LOG.error(f"File doesn't exist {src}") + result = False + + return result + + @classmethod + def create_backup(cls) -> None: + """Creates backup files with ".backup" suffix within the same directory as the source file.""" + + for src, _ in cls.paths_with_processors: + cls.sources.add(src) + + backup_len: int = len(cls.sources) + + LOG.info(f'Backing up {backup_len} file{"" if backup_len == 1 else "s"}...') + + for src in cls.sources: + backup: Path = Path(f"{src}.backup") + if backup.exists(): + LOG.info(f'Found "{backup.name}" before creation, restoring...') + shutil.copy2(backup, src) + assert filecmp.cmp(backup, src, shallow=False) + continue + + shutil.copy2(src, backup) + assert filecmp.cmp(src, backup, shallow=False) + LOG.debug(f'Created "{backup.name}"') + + if backup_len > 0: + cls.backup_state = BackupState.CREATED + + @classmethod + def restore_backup(cls) -> None: + """Restores backup files and deletes them after""" + + if cls.backup_state != BackupState.CREATED: + return + + backup_len: int = len(cls.sources) + + LOG.info(f'Restoring {backup_len} file{"" if backup_len == 1 else "s"}...') + for src in cls.sources: + backup: Path = Path(f"{src}.backup") + if not backup.exists(): + LOG.error(f'Backup "{backup.name}" doesn\'t exist') + continue + + shutil.copy2(backup, src) + assert filecmp.cmp(backup, src, shallow=False) + backup.unlink() + LOG.debug(f'Restored "{src.name}"') + + cls.backup_state = BackupState.NONE + + @classmethod + def load_section(cls, *, partial: Path, tokens: Dict[str, str], end_level: int) -> str: + """Load the section for a given partial together with some validation""" + + content: str = partial.read_text(encoding="utf8") + lines: List[str] = [] + section_started: bool = False + section_ended: bool = False + + for line in content.split("\n"): + if tokens["START"] in line: + section_started = True + if end_level < 0: + end_level = len(line) - len(line.lstrip()) + + if section_started: + lines.append(line) + if tokens["END"] in line and (len(line) - len(line.lstrip())) == end_level: + section_ended = True + break + + loaded_section: str = "\n".join(lines) + + # Validate that the loaded section started and ended + # Theme update, or another dynamic hook could have removed needed tokens + if not section_ended or not section_started: + message: str = "started" if not section_started else "ended" + LOG.error(f'Section in file "{partial.name}" never {message}') + cls.write_log(loaded_section, f"{partial.name}_read_error.html") + return "" + + # Validate that the loaded section contains all tokens + # Theme update, or another dynamic hook could have removed needed tokens + try: + for value in tokens.values(): + assert value in loaded_section + except AssertionError: + LOG.error(f'Section mismatch in "{partial.name}"') + log_content = "" + for value in tokens.values(): + log_content += f"{value in loaded_section} - {value}\n" + cls.write_log(log_content + loaded_section, f"{partial.name}_mismatch.html") + return "" + + return loaded_section + + @classmethod + def save_section(cls, *, partial: Path, original_section: str, modified_section: str) -> None: + """Save partial with modified section""" + + content: str = partial.read_text(encoding="utf8") + partial.write_text( + data=content.replace(original_section, modified_section), encoding="utf8" + ) + + @classmethod + def write_log(cls, content: str, file_name: str) -> None: + """Write `content` to TEMP_DIR/`file_name`""" + crash_log = Path(tempfile.gettempdir()) / file_name + crash_log.write_text(data=content, encoding="utf8") + LOG.info(f'File saved "{crash_log}"') + + backup_state: BackupState + """Status of the backup process""" + + sources: Set[Path] + """Set of source file paths, which will be backed up.""" + + paths_with_processors: List[Tuple[Path, Callable]] + """List of tuple pairs of file paths and their processing functions. + + Each function gets called with the following parameters in the `on_env` event: + + - partial: pathlib.Path + - config: mkdocs.config.defaults.MkDocsConfig + - env: jinja2.Environment + - files: Files + """ + + +# endregion + + +# region Constants + +HOOK_NAME: str = "theme_overrides_manager" +"""Name of this hook. Used in logging.""" + +LOG: PrefixedLogger = PrefixedLogger( + HOOK_NAME, logging.getLogger("mkdocs.hooks.theme_overrides.__main__") +) +"""Logger instance for this hook.""" + +# endregion diff --git a/overrides/assets/icons/spacer-bool.png b/overrides/assets/icons/spacer-bool.png new file mode 100644 index 0000000000..693a514bfc Binary files /dev/null and b/overrides/assets/icons/spacer-bool.png differ diff --git a/overrides/assets/icons/spacer-class.png b/overrides/assets/icons/spacer-class.png new file mode 100644 index 0000000000..71a64637b5 Binary files /dev/null and b/overrides/assets/icons/spacer-class.png differ diff --git a/overrides/assets/icons/spacer-color.png b/overrides/assets/icons/spacer-color.png new file mode 100644 index 0000000000..efd9bf2514 Binary files /dev/null and b/overrides/assets/icons/spacer-color.png differ diff --git a/overrides/assets/icons/spacer-enum.png b/overrides/assets/icons/spacer-enum.png new file mode 100644 index 0000000000..86871d444a Binary files /dev/null and b/overrides/assets/icons/spacer-enum.png differ diff --git a/overrides/assets/icons/spacer-float.png b/overrides/assets/icons/spacer-float.png new file mode 100644 index 0000000000..18278ed923 Binary files /dev/null and b/overrides/assets/icons/spacer-float.png differ diff --git a/overrides/assets/icons/spacer-folder.png b/overrides/assets/icons/spacer-folder.png new file mode 100644 index 0000000000..6a1236d820 Binary files /dev/null and b/overrides/assets/icons/spacer-folder.png differ diff --git a/overrides/assets/icons/spacer-int.png b/overrides/assets/icons/spacer-int.png new file mode 100644 index 0000000000..beb3f0bea8 Binary files /dev/null and b/overrides/assets/icons/spacer-int.png differ diff --git a/overrides/assets/icons/spacer-misc.png b/overrides/assets/icons/spacer-misc.png new file mode 100644 index 0000000000..f03426fcce Binary files /dev/null and b/overrides/assets/icons/spacer-misc.png differ diff --git a/overrides/assets/icons/spacer-string.png b/overrides/assets/icons/spacer-string.png new file mode 100644 index 0000000000..7c6f70fbb3 Binary files /dev/null and b/overrides/assets/icons/spacer-string.png differ diff --git a/overrides/assets/icons/spacer-vec.png b/overrides/assets/icons/spacer-vec.png new file mode 100644 index 0000000000..0f88b1d306 Binary files /dev/null and b/overrides/assets/icons/spacer-vec.png differ diff --git a/overrides/assets/images/c_menu_item_farmesize.png b/overrides/assets/images/c_menu_item_farmesize.png new file mode 100644 index 0000000000..b2769a5c28 Binary files /dev/null and b/overrides/assets/images/c_menu_item_farmesize.png differ diff --git a/overrides/assets/images/union_sdk_getting_started_messagebox.png b/overrides/assets/images/union_sdk_getting_started_messagebox.png new file mode 100644 index 0000000000..481b1c0b86 Binary files /dev/null and b/overrides/assets/images/union_sdk_getting_started_messagebox.png differ diff --git a/overrides/assets/images/zSpy.png b/overrides/assets/images/zSpy.png new file mode 100644 index 0000000000..7c3d4cbe92 Binary files /dev/null and b/overrides/assets/images/zSpy.png differ diff --git a/overrides/assets/javascripts/extra.js b/overrides/assets/javascripts/extra.js index bba6dbf750..1687025f2e 100644 --- a/overrides/assets/javascripts/extra.js +++ b/overrides/assets/javascripts/extra.js @@ -100,13 +100,18 @@ window.addEventListener("DOMContentLoaded", _ => { gmcExpandNavigation(); gmcAddVersionToggle(); gmcLinksForVersion(); - if (gGMC_PAGE_LOCALE !== gGMC_DEFAULT_LOCALE && gGMC_PAGE_LOCALE !== gGMC_PAGE_FILE_LOCALE) { + if (gGMC_PAGE_LOCALE !== gGMC_DEFAULT_LOCALE + && gGMC_PAGE_LOCALE !== gGMC_FILE_LOCALE + && !gGMC_REMOVE_TRANSLATION_PROMPTS) { gmcTranslateButton(); } gmcRemoveCodeLines(); gmcExternalLinks(); - new gMutationObserver(gmcSearchMutationCallback) - .observe(document.querySelector(".md-search-result__list"), {childList: true}); + const searchResults = document.querySelector(".md-search-result__list"); + if (searchResults) { + new gMutationObserver(gmcSearchMutationCallback) + .observe(searchResults, {childList: true}); + } }); window.addEventListener("hashchange", _ => { @@ -155,17 +160,19 @@ function gmcExpandNavigation() { return; } - const activeLink = document.querySelector(".md-nav__link--active"); + const activeLinkLabel = document.querySelector("label.md-nav__link--active"); - if (!activeLink) { + if (!activeLinkLabel) { return; } - let activeNav = activeLink.parentElement.querySelector("nav"); + const navID = activeLinkLabel.id; + + let activeNav = document.querySelector(`nav[aria-labelledby="${navID}"]`); if (!activeNav || activeNav.className.includes("md-nav--secondary")) { - // gmcDebug(`nav not foundInParent`); - activeNav = activeLink.closest("nav"); + // gmcDebug(`nav with id ${navID} not found`); + activeNav = activeLinkLabel.closest("nav"); } if (activeNav.dataset.hasOwnProperty("mdLevel")) { @@ -402,6 +409,7 @@ const gmcTranslateButton = () => { "*GitHub's file editor doesn't provide `.md` formatting options, if you want those, consider using https://stackedit.io/*", ].join(" \n")); const newAnchor = document.createElement("a"); + newAnchor.id = "gmc-new-translation-button"; newAnchor.classList = anchor.classList; // Weird quirk. The topDirectory needs to be in both, the link and in the filename param to put the file in the correct directory. // -- This quirk stopped quirking with the introduction of the new GitHub UI, sadge. @@ -409,7 +417,7 @@ const gmcTranslateButton = () => { newAnchor.innerHTML = gGMC_TRANSLATE_SVG; newAnchor.title = gGMC_TRANSLATE_CTA; anchor.parentElement.prepend(newAnchor); -} +}; const gmcRemoveCodeLines = () => { const nodesForRemoval = []; @@ -426,13 +434,14 @@ const gmcRemoveCodeLines = () => { }; const gmcFadingNavigation = () => { - const activeNavItems = document.querySelectorAll(".md-nav__item--active"); + const activeNavItems = document.querySelectorAll(".md-nav__item--active.md-nav__item--nested"); if (activeNavItems.length <= 1) return; activeNavItems[0].classList.add("gmc-fade-nav"); -} + activeNavItems[activeNavItems.length - 1].classList.add("gmc-fade-nav-off"); +}; function gmcDebug(...message) { if (gGMC_LOCAL) diff --git a/overrides/assets/javascripts/preferences.js b/overrides/assets/javascripts/preferences.js new file mode 100644 index 0000000000..964c5fdb5d --- /dev/null +++ b/overrides/assets/javascripts/preferences.js @@ -0,0 +1,253 @@ +/* + * Licence MIT - Copyright (c) 2024 Kamil Krzyśków (HRY) + */ + +const gmcPreferenceHandler = (event) => { + console.debug(event); + const target = event.target; + const option = target.dataset["option"]; + // preferencesKey defined in extrahead template override + let loadedPreferences = __md_get(preferencesKey); + if (!loadedPreferences[option]) { + loadedPreferences[option] = {}; + } + + // TODO reconsider the OOP approach idea + const optionHandlers = { + "color": updateColorPreference, + "custom": () => { + loadedPreferences[option]["cssRaw"] = target.value; + }, + "font": updateFontPreference, + }; + + if (optionHandlers[option]) { + optionHandlers[option](option, target, loadedPreferences); + } else { + console.error("Unhandled option", option, target.value); + } + + updateGlobalPreferences(loadedPreferences); + __md_set(preferencesKey, loadedPreferences); + // Function defined in extrahead template override + gmcLoadSetPreferences(); +}; + +const updateColorPreference = (option, target, loadedPreferences) => { + const extra = target.dataset["extra"]; + const handle = loadedPreferences[option]; + if (extra === "reset") { + loadedPreferences[option] = {}; + document.querySelector(`#preference-color-accent`).value = "#000000"; + document.querySelector(`#preference-color-hue`).value = "#000000"; + return; + } + // Credit: https://stackoverflow.com/questions/3732046/how-do-you-get-the-hue-of-a-xxxxxx-colour + const hexColor = target.value; + const red = parseInt(hexColor.substr(1, 2), 16); + const green = parseInt(hexColor.substr(3, 2), 16); + const blue = parseInt(hexColor.substr(5, 2), 16); + let [hue, _, lightness] = rgbToHsl(red, green, blue); + hue = Math.floor(hue * 360); + lightness = Math.round(lightness * 240); + + const mod = 20; + const redDarkerHex = Math.max(red - mod, 0).toString(16).padStart(2, "0"); + const greenDarkerHex = Math.max(green - mod, 0).toString(16).padStart(2, "0"); + const blueDarkerHex = Math.max(blue - mod, 0).toString(16).padStart(2, "0"); + const darkerColorHex = `#${redDarkerHex}${greenDarkerHex}${blueDarkerHex}`; + + if (!handle[extra]) { + handle[extra] = {}; + } + + handle[extra]["value"] = target.value; + if (extra === "hue") { + handle[extra]["calculatedHue"] = hue; + } else if (extra === "accent") { + handle[extra]["darker"] = darkerColorHex; + handle[extra]["calculatedHue"] = hue; + } + + handle["cssRaw"] = "*, :before, :after { "; + if (handle["hue"]) { + handle["cssRaw"] += `--md-hue: ${handle["hue"]["calculatedHue"]}deg;`; + } + if (handle["accent"]) { + handle["cssRaw"] += `--gmc-tabs-bg-hue: ${handle["accent"]["calculatedHue"]}deg;`; + handle["cssRaw"] += `--md-accent-fg-color: ${handle["accent"]["value"]};`; + handle["cssRaw"] += `--md-accent-fg-color--transparent: ${handle["accent"]["value"]}1a;`; + handle["cssRaw"] += `--md-typeset-a-color: ${handle["accent"]["darker"]};` + if (lightness > 120) { + handle["cssRaw"] += "--md-accent-bg-color: #000000de;"; + handle["cssRaw"] += "--md-accent-bg-color--light: #0000008a;" + } else { + handle["cssRaw"] += "--md-accent-bg-color: #fff;"; + handle["cssRaw"] += "--md-accent-bg-color--light: #ffffffb3;" + } + } + handle["cssRaw"] += " }\n"; +} + +const updateFontPreference = (option, target, loadedPreferences) => { + const handle = loadedPreferences[option]; + handle["value"] = target.value; + handle["cssRaw"] = ""; + + if (target.value === "opendyslexic") { + // Due to the JavaScript CSS injection -> Import Fetch there is a delay + // when it comes to enabling the custom font. The default font flashes for a second or 2. + // Only fix for this would be to remove the import and inject the CSS font file directly, + // however that is not ideal either. + handle["cssRaw"] += `@import url('https://fonts.cdnfonts.com/css/opendyslexic'); + :root { --md-text-font: "OpenDyslexic"; --md-code-font: "OpenDyslexicMono"; }`; + } + // Initial attempt that didn't work due to CORS, but is valid for adding CSS based on the font URLs. + // Doesn't handle TTF or OTF fonts, only WOFF/2. + // if (target.value === "opendyslexic") { + // const fontUrls = [ + // "https://github.com/antijingoist/opendyslexic/raw/master/compiled/OpenDyslexic-Regular.woff2", + // "https://github.com/antijingoist/opendyslexic/raw/master/compiled/OpenDyslexic-Italic.woff2", + // "https://github.com/antijingoist/opendyslexic/raw/master/compiled/OpenDyslexic-Bold.woff", + // "https://github.com/antijingoist/opendyslexic/raw/master/compiled/OpenDyslexic-Bold-Italic.woff2", + // ]; + // for (const url of fontUrls) { + // const fileName = url.split("/").pop(); + // const fontName = fileName.split("-")[0]; + // const formatName = fileName.split(".").pop(); + // let currentFont = `@font-face { font-family: "${fontName}"; `; + // if (fontName.toLowerCase().includes("bold")) { + // currentFont += "font-weight: bold; "; + // } + // if (fontName.toLowerCase().includes("bold")) { + // currentFont += "font-style: italic; "; + // } + // currentFont += `src: local("${fontName}"), url("${url}") format("${formatName}"); }\n` + // handle["cssRaw"] += currentFont; + // } + // handle["cssRaw"] += ':root { --md-text-font: "OpenDyslexic"; }' + // } +} + +const updateGlobalPreferences = (loadedPreferences) => { + loadedPreferences["__global"]["cssRaw"] = ""; + + const imports = []; + for (let key in loadedPreferences) { + if (key === "__global" || !loadedPreferences[key]["cssRaw"]) continue; + const lines = loadedPreferences[key]["cssRaw"].split("\n"); + for (const line of lines) { + if (line.includes("@import")) { + imports.push(line); + } else { + loadedPreferences["__global"]["cssRaw"] += line + "\n"; + } + } + } + + if (imports) { + loadedPreferences["__global"]["cssRaw"] = imports.join("\n") + "\n" + loadedPreferences["__global"]["cssRaw"]; + } +} + +/** + * Removes the translation prompts from the page. + * Mostly a quick hack for the GMC Preferences page. + * Once this function is used more than 3 times, + * it would be better to have a backend preprocessor solution. + */ +const removeRedundantTranslationIndicator = () => { + // TODO backend preprocessor solution + const itemsToRemove = [ + document.querySelector("#gmc-new-translation-button"), + document.querySelector(".gmc-announce") + ]; + + for (const item of itemsToRemove) { + // console.debug(item); + if (item) { + item.remove(); + } + } +}; + +/* + This is run immediately when loaded to limit UI elements flashing. +*/ +(() => { + + // Defined in extrahead template override + gGMC_REMOVE_TRANSLATION_PROMPTS = true; + removeRedundantTranslationIndicator(); + + const loadedPreferences = __md_get(preferencesKey); + const options = ["color-accent", "color-hue", "color-reset", "font", "custom"]; + + for (const option of options) { + const el = document.querySelector(`#preference-${option}`); + const split = option.split("-"); + const handle = loadedPreferences[option]; + if (handle) { + const value = handle["value"] || handle["cssRaw"]; + if (value) { + el.value = value; + } + } else if (split.length === 2 && loadedPreferences[split[0]] && loadedPreferences[split[0]][split[1]]) { + const value = loadedPreferences[split[0]][split[1]]["value"]; + if (value) { + el.value = value; + } + } + if (el.tagName.toLowerCase() === "a") { + el.addEventListener("click", gmcPreferenceHandler); + } else { + el.addEventListener("change", gmcPreferenceHandler); + } + } + +})(); + +/** + * Converts an RGB color value to HSL. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and l in the set [0, 1]. + * + * Credit: https://gist.github.com/mjackson/5311256 + * + * @return Array The HSL representation + * @param r + * @param g + * @param b + */ +function rgbToHsl(r, g, b) { + r /= 255; + g /= 255; + b /= 255; + + const max = Math.max(r, g, b), min = Math.min(r, g, b); + let h, s, l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + + h /= 6; + } + + return [h, s, l]; +} \ No newline at end of file diff --git a/overrides/assets/stylesheets/constants.css b/overrides/assets/stylesheets/constants.css index 0fa956a1b4..a959467188 100644 --- a/overrides/assets/stylesheets/constants.css +++ b/overrides/assets/stylesheets/constants.css @@ -8,4 +8,10 @@ --gmc-external-svg: url('data:image/svg+xml;charset=utf-8,'); /* SVG to CSS inline data converter: https://yoksel.github.io/url-encoder/ - output edited */ --md-admonition-icon--trivia: url('data:image/svg+xml;charset=utf-8,'); +} + +/* Color */ +:root { + --gmc-blue-tint: #00aafc; + --gmc-tabs-bg-hue: 210deg; } \ No newline at end of file diff --git a/overrides/assets/stylesheets/extra.css b/overrides/assets/stylesheets/extra.css index 257ede8386..97137b63f8 100644 --- a/overrides/assets/stylesheets/extra.css +++ b/overrides/assets/stylesheets/extra.css @@ -5,13 +5,14 @@ /* Add opacity to the less important parts of the page */ /* Adapted from https://github.com/AhmedThahir/Uni_Notes/blob/f3a59864f77d7a52d3e21e1007f9cd5c50ab5c66/docs/stylesheets/custom.css#L28-L44 */ @media screen and (min-width: 76.1875em) and (orientation: landscape) { + .md-nav--primary :is(.dummy-for-compressor) { display: none } + .md-nav--primary :is(a, label) { will-change: opacity; transition: opacity 0.4s !important; } - .gmc-fade-nav li:not(li:has(.md-nav__link--active), .md-nav--primary:hover li) :is(a, label) - { + .gmc-fade-nav li:not(li:has(.md-nav__link--active), .md-nav--primary:hover li, .gmc-fade-nav-off li) :is(a, label) { opacity: 0.2; } } @@ -22,6 +23,18 @@ max-width: 75rem; } +/* override md-main on the page */ +@media screen { + [data-md-color-scheme=slate] { + --md-default-fg-color: hsla(var(--md-hue), 15%, 90%, 1); + } +} + +/* Add left padding indent to the content */ +article > div > :is(:not(h1, h2, h3, h4)) { + padding-left: 1em !important; +} + /* Shrink header and footer to the content size*/ .md-grid { /* Default 61rem */ @@ -95,7 +108,7 @@ div.md-nav__link--index { --md-accent-fg-color: #0b65b0; } [data-md-color-scheme=slate] { - --md-accent-fg-color: #00aafc; + --md-accent-fg-color: var(--gmc-blue-tint); } } @@ -109,6 +122,7 @@ div.md-nav__link--index { .md-typeset :is(h1, h2, h3, h4, h5, h6) { font-weight: 700; color: var(--md-default-fg-color--light); + text-shadow: 0 0 0 var(--md-default-fg-color--light); } .md-typeset :is(h3, h4, h5, h6) { @@ -124,9 +138,7 @@ div.md-nav__link--index { } @media { - [data-md-color-scheme=slate] :is(.dummy-for-compressor) { - display: none; - } + [data-md-color-scheme=slate] :is(.dummy-for-compressor) { display: none } /*--md-default-fg-color--light:hsla(var(--md-hue),75%,90%,0.62);*/ [data-md-color-scheme=slate] :is(h1, h2, h3, h4, h5, h6) { --md-default-fg-color--light: hsla(var(--md-hue), 100%, 100%, 1); @@ -171,16 +183,13 @@ div.md-nav__link--index { /* override tabs navigation */ @media { [data-md-color-scheme="slate"] .md-header { - border-bottom: 0.10rem solid var(--md-accent-fg-color); + outline: .10rem solid var(--md-accent-fg-color); } - [data-md-color-scheme="slate"] .md-tabs__link--active { + [data-md-color-scheme="slate"] .md-tabs__item--active a.md-tabs__link { color: var(--md-accent-fg-color); } - [data-md-color-scheme="default"] .md-header { - border-bottom: 0.10rem solid #000; - } [data-md-color-scheme="slate"] .md-tabs { - background-color: hsla(210, 100%, 20%, 1) !important; + background-color: hsla(var(--gmc-tabs-bg-hue), 100%, 20%, 1); } } diff --git a/overrides/main.html b/overrides/main.html index a6a6e8e9ce..31b35c35d5 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -1,5 +1,37 @@ {% extends "base.html" %} +{% block extrahead %} + {{ super() }} + +{% endblock %} + {# Extend the last block in the `base.html` before the changes are applicable to avoid any issues with the hacky page.meta @@ -9,14 +41,11 @@ {{ super() }} {% if page %} {% if not page.meta %} - {# Set page.meta to a hacky reference of the page itself #} - {% set _ = page.__setattr__("meta", page) %} - {# Let It Snow by setting the page object attribute #} - {% set _ = page.meta.__setattr__("ᴴₒᴴₒᴴₒ", True) %} - {% else %} - {# Let It Snow by updating the dict/mapping pair #} - {% set _ = page.meta.update({"ᴴₒᴴₒᴴₒ": True}) %} + {# Set page.meta to an empty dict/mapping #} + {% set _ = page.__setattr__("meta", {}) %} {% endif %} + {# Let It Snow by updating the dict/mapping pair #} + {% set _ = page.meta.update({"ᴴₒᴴₒᴴₒ": True}) %} {% endif %} {% endblock %} @@ -35,7 +64,7 @@ "cs": "Podpoř nás a pomoz nám s překladem!", } %} - {% if i18n_page_locale != "en" and i18n_page_file_locale != i18n_page_locale %} + {% if i18n_page_locale != "en" and i18n_file_locale != i18n_page_locale %}
{{ announcement[i18n_page_locale] }} {{ call_to_action[i18n_page_locale] }} @@ -46,7 +75,7 @@ const gGMC_SELECT_VERSION = "{{ lang.t('select.version') }}"; const gGMC_TRANSLATE_CTA = "{{ call_to_action[i18n_page_locale] }}"; const gGMC_PAGE_LOCALE = "{{ i18n_page_locale }}"; - const gGMC_PAGE_FILE_LOCALE = "{{ i18n_page_file_locale }}"; + const gGMC_FILE_LOCALE = "{{ i18n_file_locale }}"; const gGMC_TRANSLATE_SVG = '{% include ".icons/material/web-plus.svg" %}'; {# Include original content after the additions #} diff --git a/requirements-deploy.txt b/requirements-deploy.txt new file mode 100644 index 0000000000..44368749d6 --- /dev/null +++ b/requirements-deploy.txt @@ -0,0 +1,4 @@ +# Deployment Requirements +# Could be replaced with `pip install mkdocs-material[imaging]` in the future +Pillow==10.1.0 +CairoSVG==2.7.1 diff --git a/requirements.txt b/requirements.txt index a4b4283cb1..546b5cd34a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ -mkdocs-material==9.1.5 -mkdocs-git-revision-date-localized-plugin==1.2.0 +# Core Requirements +mkdocs-material==9.5.8 +mkdocs-git-revision-date-localized-plugin==1.2.1 mkdocs-video==1.5.0 -mkdocs-redirects==1.2.0 -mkdocs-minify-plugin==0.6.4 -# mkdocs-static-i18n==0.53 -git+https://github.com/kamilkrzyskow/i18n.git@920d38313b60812e8e03dba88a856bfdd41527dc#egg=mkdocs_static_i18n +mkdocs-redirects==1.2.1 +mkdocs-minify-plugin==0.7.1 +mkdocs-static-i18n==1.2.0 git+https://github.com/kamilkrzyskow/gothic-lexer.git@b5ee7868a7e7397cd129ff1f847daa7d39c0e416#egg=gothic_lexer -# mkdocs-awesome-pages-plugin==2.8.0 -git+https://github.com/kamilkrzyskow/awesome-pages.git@b0c544a92733977e09ac23c7f9238d13012f4fd9#egg=mkdocs_awesome_pages_plugin \ No newline at end of file +mkdocs-awesome-pages-plugin==2.9.2 + diff --git a/tests/test_localization.py b/tests/test_localization.py index 255fe4c43b..634d42734c 100644 --- a/tests/test_localization.py +++ b/tests/test_localization.py @@ -5,12 +5,12 @@ import json import os import unittest + import regex # noinspection PyPackageRequirements -import yaml - -from tests.path_constants import DOCS_DIR, OVERRIDES_DIR, ROOT_DIR +from mkdocs.utils import yaml_load +from path_constants import DOCS_DIR, OVERRIDES_DIR, ROOT_DIR class LocalizationTest(unittest.TestCase): @@ -19,18 +19,54 @@ class LocalizationTest(unittest.TestCase): """ config: dict = None + settings_to_check: list[tuple] = None + expected_settings: dict = None @classmethod def setUpClass(cls) -> None: with open(os.path.join(ROOT_DIR, "mkdocs.yml"), encoding="utf8") as file: - lines = file.readlines() - - # The default safe loader doesn't handle values containing !, they're not needed for localization - # for the exception of !ENV which are important - lines = [regex.sub(r"!ENV.*,\s*?(\w+)\]", r"\g<1>", line) for line in lines] - output = "\n".join([regex.sub(r"!.*", "", line) for line in lines]) - - for plugin in yaml.safe_load(output)["plugins"]: + content = file.read() + + # Extract the ENV options, and assert that the selected boolean variables + # are set to the correct boolean values (aka weren't changed by mistake) + dirty_settings = regex.findall(r"\s*(.*?):\s*!ENV\s*\[(.*?)\]", content) + cls.settings_to_check = [] + + # Assure only controlled cases use undefined fallback values + allow_undefined = { + "GMC_DEV_LOCALE", + } + + # some settings might have multiple !ENV toggles, so the catch all regex + # result needs to be cleaned up + for setting_group in dirty_settings: + if len(setting_group) != 2: + raise ValueError("Unhandled case setting_group isn't 2 values") + + prop_name, envar = setting_group + + fallback_value = None + splitted = list(map(str.strip, envar.split(","))) + + if splitted[-1].lower() in {"true", "false"} or "'" in splitted[-1]: + fallback_value = eval(splitted.pop()) + + if fallback_value is None: + for var in splitted: + if var not in allow_undefined: + raise ValueError( + f"{prop_name} - {envar} should also define a default fallback" + ) + else: + for var in splitted: + cls.settings_to_check.append((prop_name, var, fallback_value)) + + cls.expected_settings = { + "GMC_ENABLE_ON_PUBLISH": False, + "GMC_BUILD_ALTERNATES": False, + } + + for plugin in yaml_load(content)["plugins"]: if isinstance(plugin, dict): cls.config = plugin.get("i18n") if cls.config is not None: @@ -38,28 +74,41 @@ def setUpClass(cls) -> None: def setUp(self) -> None: self.assertIsNot(self.config, None, msg="Localization config is None") + for setting_name, envar_name, actual in self.settings_to_check: + if envar_name not in self.expected_settings: + continue + expected = self.expected_settings[envar_name] + self.assertEqual( + actual, + expected, + msg=f"Setting '{setting_name}'->{envar_name} is set to {actual} instead of {expected}", + ) def test_default(self) -> None: """ Test that the default language is properly set, and that all languages are built """ default = "en" - self.assertEqual( - self.config["default_language"], default, msg=f"Default must be '{default}'" - ) - self.assertTrue( - default in self.config["languages"], msg=f"Language selector must contain '{default}'" - ) - self.assertFalse( - self.config["default_language_only"], msg=f"All languages must be deployed" - ) + default_present = False + + for lang in self.config["languages"]: + lang_default = lang.get("default", False) + if lang["locale"] == default: + default_present = True + self.assertTrue(lang_default, msg=f"'{default}' must be set Default") + else: + self.assertFalse(lang_default, msg=f"Only '{default}' can be set Default") + self.assertTrue( + lang["build"], msg=f"All languages must be deployed - '{lang['locale']}' isn't" + ) + + self.assertTrue(default_present, msg=f"Language selector must contain '{default}'") def test_announcement(self) -> None: """ Test that every localization has an announcement for untranslated content """ - languages = list(self.config["languages"].keys()) - languages.remove("en") + languages: list = self.config["languages"] with open(os.path.join(OVERRIDES_DIR, "main.html"), encoding="utf8") as file: main = file.read() @@ -93,13 +142,14 @@ def test_announcement(self) -> None: action = json.loads(regex.sub(r",\s*}", "}", regex.sub(r"\s+", " ", action_content))) for language in languages: + locale = language["locale"] self.assertTrue( - language in announcement and language in action, - msg=f"'{language}' is missing from at least one of the announcement dicts in main.html", + locale in announcement and locale in action, + msg=f"'{locale}' is missing from at least one of the announcement dicts in main.html", ) self.assertTrue( - len(announcement[language]) > 0 and len(action[language]) > 0, - msg=f"'{language}' is empty in at least one of the announcement dicts in main.html", + len(announcement[locale]) > 0 and len(action[locale]) > 0, + msg=f"'{locale}' is empty in at least one of the announcement dicts in main.html", ) def test_files(self) -> None: