diff --git a/.eslintrc.json b/.eslintrc.json
index 067f47e1f..c317f7a67 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,249 +1,187 @@
{
- "env": {
- "browser": true,
- "node": true
- },
- "extends": [
- "eslint:recommended",
- "plugin:jest/style",
- "plugin:@typescript-eslint/eslint-recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:import/errors",
- "plugin:import/typescript"
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:import/errors",
+ "plugin:import/typescript",
+ "plugin:jest/style",
+ "plugin:jsdoc/recommended"
+ ],
+ "ignorePatterns": [
+ "target/**/*",
+ // Typescript plugins typing check cause eslint issues, takes too much time for few files
+ "cli/build/plugins/**/*"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "jest", "import", "sort-keys-fix"],
+ "rules": {
+ "@typescript-eslint/no-misused-new": "off",
+ "@typescript-eslint/ban-ts-comment": "off",
+ "@typescript-eslint/ban-ts-ignore": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-member-accessibility": ["error"],
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "@typescript-eslint/no-empty-function": "off",
+ "@typescript-eslint/no-empty-interface": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "jsdoc/require-param-type": "off",
+ "jsdoc/require-returns-type": "off",
+ "jsdoc/tag-lines": ["error", "any", { "startLines": 1, "endLines": 0 }],
+ "jsdoc/check-tag-names": "off",
+ "jsdoc/require-param": "off",
+ "jsdoc/require-returns": "off",
+ "jsdoc/require-param-description": "off",
+ "jsdoc/require-jsdoc": "off",
+ "array-element-newline": ["error", "consistent"],
+ "arrow-parens": ["error", "always"],
+ "arrow-spacing": "error",
+ "brace-style": "error",
+ "camelcase": "off",
+ "sort-vars": "error",
+ "sort-imports": [
+ "error",
+ {
+ "ignoreCase": true,
+ "ignoreDeclarationSort": true,
+ "ignoreMemberSort": false,
+ "allowSeparatedGroups": false
+ }
],
- "ignorePatterns": [
- "target/**/*",
- // Typescript plugins typing check cause eslint issues, takes too much time for few files
- "cli/build/plugins/**/*"
+ "comma-dangle": [
+ "error",
+ {
+ "arrays": "always-multiline",
+ "objects": "always-multiline",
+ "imports": "always-multiline",
+ "exports": "never",
+ "functions": "never"
+ }
],
- "parser": "@typescript-eslint/parser",
- "plugins": [
- "@typescript-eslint",
- "jest",
- "import",
- "sort-keys-fix"
+ "eqeqeq": "error",
+ "eol-last": ["error", "always"],
+ "func-call-spacing": ["error", "never"],
+ "function-paren-newline": ["error", "multiline-arguments"],
+ "import/default": "off",
+ "import/no-relative-parent-imports": "error",
+ "import/no-unresolved": "off",
+ "import/order": [
+ "error",
+ {
+ "alphabetize": {
+ "caseInsensitive": true,
+ "order": "asc"
+ },
+ "groups": ["builtin", "external", "parent", "sibling", "index"],
+ "newlines-between": "always",
+ "pathGroups": [
+ {
+ "group": "external",
+ "pattern": "#/**",
+ "position": "after"
+ },
+ {
+ "group": "external",
+ "pattern": "@/**",
+ "position": "after"
+ }
+ ],
+ "pathGroupsExcludedImportTypes": ["builtin"]
+ }
],
- "rules": {
- "@typescript-eslint/no-misused-new": "off",
- "@typescript-eslint/ban-ts-comment": "off",
- "@typescript-eslint/ban-ts-ignore": "off",
- "@typescript-eslint/explicit-function-return-type": "off",
- "@typescript-eslint/explicit-member-accessibility": [
- "error"
- ],
- "@typescript-eslint/explicit-module-boundary-types": "off",
- "@typescript-eslint/no-empty-function": "off",
- "@typescript-eslint/no-empty-interface": "off",
- "@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/no-inferrable-types": "off",
- "@typescript-eslint/no-non-null-assertion": "off",
- "@typescript-eslint/no-unused-vars": "off",
- "array-element-newline": [
- "error",
- "consistent"
- ],
- "arrow-parens": [
- "error",
- "always"
- ],
- "arrow-spacing": "error",
- "brace-style": "error",
- "camelcase": "off",
- "sort-vars": "error",
- "sort-imports": ["error", {
- "ignoreCase": true,
- "ignoreDeclarationSort": true,
- "ignoreMemberSort": false,
- "allowSeparatedGroups": false
- }],
- "comma-dangle": [
- "error",
- {
- "arrays": "always-multiline",
- "objects": "always-multiline",
- "imports": "always-multiline",
- "exports": "never",
- "functions": "never"
- }
- ],
- "eqeqeq": "error",
- "eol-last": [
- "error",
- "always"
- ],
- "func-call-spacing": [
- "error",
- "never"
- ],
- "function-paren-newline": [
- "error",
- "multiline-arguments"
- ],
- "import/default": "off",
- "import/no-relative-parent-imports": "error",
- "import/no-unresolved": "off",
- "import/order": [
- "error",
- {
- "alphabetize": {
- "caseInsensitive": true,
- "order": "asc"
- },
- "groups": [
- "builtin",
- "external",
- "parent",
- "sibling",
- "index"
- ],
- "newlines-between": "always",
- "pathGroups": [
- {
- "group": "external",
- "pattern": "#/**",
- "position": "after"
- },
- {
- "group": "external",
- "pattern": "@/**",
- "position": "after"
- }
- ],
- "pathGroupsExcludedImportTypes": [
- "builtin"
- ]
- }
- ],
- "indent": [
- "error",
- 2,
- {
- "SwitchCase": 1
- }
- ],
- "key-spacing": [
- "error",
- {
- "afterColon": true,
- "beforeColon": false
- }
- ],
- "keyword-spacing": "error",
- "max-len": [
- "error",
- {
- "code": 120,
- "ignorePattern": "^import\\W.*"
- }
- ],
- "no-constructor-return": "error",
- "no-duplicate-imports": "error",
- "no-multi-spaces": "error",
- "no-multiple-empty-lines": [
- "error",
- {
- "max": 1,
- "maxBOF": 1
- }
- ],
- "no-trailing-spaces": "error",
- "object-curly-newline": [
- "error",
- {
- "consistent": true,
- "multiline": true
- }
- ],
- "object-curly-spacing": [
- "error",
- "always"
- ],
- "object-property-newline": [
- "error",
- {
- "allowAllPropertiesOnSameLine": true
- }
- ],
- "padding-line-between-statements": [
- "error",
- {
- "blankLine": "always",
- "next": "return",
- "prev": "*"
- },
- {
- "blankLine": "always",
- "next": [
- "const",
- "let",
- "var"
- ],
- "prev": "expression"
- },
- {
- "blankLine": "always",
- "next": "*",
- "prev": [
- "const",
- "let",
- "var"
- ]
- },
- {
- "blankLine": "always",
- "next": "*",
- "prev": [
- "for",
- "if",
- "while",
- "do",
- "with"
- ]
- },
- {
- "blankLine": "always",
- "next": [
- "function",
- "class"
- ],
- "prev": [
- "function",
- "class"
- ]
- },
- {
- "blankLine": "any",
- "next": [
- "const",
- "let",
- "var"
- ],
- "prev": [
- "const",
- "let",
- "var"
- ]
- }
- ],
- "quotes": [
- "error",
- "double"
- ],
- "semi": "error",
- "space-in-parens": [
- "error",
- "never"
- ],
- "spaced-comment": [
- "error",
- "always"
- ],
- "template-tag-spacing": [
- "error",
- "never"
- ],
- "yoda": "error"
- },
- "settings": {
- }
+ "indent": [
+ "error",
+ 2,
+ {
+ "SwitchCase": 1
+ }
+ ],
+ "key-spacing": [
+ "error",
+ {
+ "afterColon": true,
+ "beforeColon": false
+ }
+ ],
+ "keyword-spacing": "error",
+ "max-len": [
+ "error",
+ {
+ "code": 120,
+ "ignorePattern": "^import\\W.*"
+ }
+ ],
+ "no-constructor-return": "error",
+ "no-duplicate-imports": "error",
+ "no-multi-spaces": "error",
+ "no-multiple-empty-lines": [
+ "error",
+ {
+ "max": 1,
+ "maxBOF": 1
+ }
+ ],
+ "no-trailing-spaces": "error",
+ "object-curly-newline": [
+ "error",
+ {
+ "consistent": true,
+ "multiline": true
+ }
+ ],
+ "object-curly-spacing": ["error", "always"],
+ "object-property-newline": [
+ "error",
+ {
+ "allowAllPropertiesOnSameLine": true
+ }
+ ],
+ "padding-line-between-statements": [
+ "error",
+ {
+ "blankLine": "always",
+ "next": "return",
+ "prev": "*"
+ },
+ {
+ "blankLine": "always",
+ "next": ["const", "let", "var"],
+ "prev": "expression"
+ },
+ {
+ "blankLine": "always",
+ "next": "*",
+ "prev": ["const", "let", "var"]
+ },
+ {
+ "blankLine": "always",
+ "next": "*",
+ "prev": ["for", "if", "while", "do", "with"]
+ },
+ {
+ "blankLine": "always",
+ "next": ["function", "class"],
+ "prev": ["function", "class"]
+ },
+ {
+ "blankLine": "any",
+ "next": ["const", "let", "var"],
+ "prev": ["const", "let", "var"]
+ }
+ ],
+ "quotes": ["error", "double"],
+ "semi": "error",
+ "space-in-parens": ["error", "never"],
+ "spaced-comment": ["error", "always"],
+ "template-tag-spacing": ["error", "never"],
+ "yoda": "error"
+ },
+ "settings": {}
}
diff --git a/README.md b/README.md
index 42534ab4c..e37d340ca 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,11 @@ Optimizations, quality and logics updates are welcome.
- [parse](cli/parse/README.md) - parsing utils to collect documentation or JSON summaries
- `help` - print list of commands and information about them
+## 💿 Build
+
+Script engine can be packaged and built into custom game package.
+Detailed description: [link](doc/BUILDING_CUSTOM_GAME_PACKAGE.md)
+
---
## 🧰 Docs
@@ -104,7 +109,11 @@ Optimizations, quality and logics updates are welcome.
## 🏗️ Assets
+Additional assets repository can be cloned manually or with shortcut command:
+`npm run cli clone *name*` (`extended`, `locale-eng`, `locale-ukr`, `locale-rus`)
+
- Extended assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-extended](https://gitlab.com/xray-forge/stalker-xrf-resources-extended)
- EN locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng)
- UA locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr)
- RU locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus)
+
diff --git a/cli/build/steps/configs_dynamic.ts b/cli/build/steps/configs_dynamic.ts
index 7c63f30b1..b4bd617ac 100644
--- a/cli/build/steps/configs_dynamic.ts
+++ b/cli/build/steps/configs_dynamic.ts
@@ -67,6 +67,9 @@ export async function buildDynamicConfigs(parameters: IBuildCommandParameters):
* Get list of LTX transformable descriptors.
*/
async function getLtxConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectLtxConfigs(
acc: Array,
it: TFolderFiles
diff --git a/cli/build/steps/configs_statics.ts b/cli/build/steps/configs_statics.ts
index cab6109e7..0114d69bf 100644
--- a/cli/build/steps/configs_statics.ts
+++ b/cli/build/steps/configs_statics.ts
@@ -53,6 +53,9 @@ export async function buildStaticConfigs(parameters: IBuildCommandParameters): P
* Get list of static configs.
*/
async function getStaticConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectConfigs(
acc: Array,
it: TFolderFiles
diff --git a/cli/build/steps/meta.ts b/cli/build/steps/meta.ts
index 879a328da..646a83bd3 100644
--- a/cli/build/steps/meta.ts
+++ b/cli/build/steps/meta.ts
@@ -17,9 +17,6 @@ interface IBuildMetaParams {
/**
* Step to collect metadata in a single file with timing metrics.
- *
- * @param meta - build meta information to save
- * @param timeTracker - build time tracker with performance metrics
*/
export async function buildMeta({ meta, timeTracker }: IBuildMetaParams): Promise {
log.info(blueBright("Build metadata"));
diff --git a/cli/build/steps/translations_dynamic.ts b/cli/build/steps/translations_dynamic.ts
index e090ed939..a59713dfe 100644
--- a/cli/build/steps/translations_dynamic.ts
+++ b/cli/build/steps/translations_dynamic.ts
@@ -35,6 +35,9 @@ export async function buildDynamicTranslations(): Promise {
return log.warn("No languages to translate found in config.json file, skip");
}
+ /**
+ * todo;
+ */
function collectTranslations(
acc: Array,
it: TFolderFiles
diff --git a/cli/build/steps/ui_dynamic.ts b/cli/build/steps/ui_dynamic.ts
index c0647d76a..ea461d0ad 100644
--- a/cli/build/steps/ui_dynamic.ts
+++ b/cli/build/steps/ui_dynamic.ts
@@ -63,6 +63,9 @@ export async function buildDynamicUi(parameters: IBuildCommandParameters): Promi
* Get list of UI config files in engine source files.
*/
async function getUiConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectXmlConfigs(
acc: Array,
it: TFolderFiles
diff --git a/cli/build/steps/ui_statics.ts b/cli/build/steps/ui_statics.ts
index 5d18a06a1..0060b3695 100644
--- a/cli/build/steps/ui_statics.ts
+++ b/cli/build/steps/ui_statics.ts
@@ -51,6 +51,9 @@ export async function buildStaticUi(parameters: IBuildCommandParameters): Promis
* Get UI configuration files list.
*/
async function getUiConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectXmlConfigs(
acc: Array,
it: Array | string
diff --git a/cli/format/format_ltx.ts b/cli/format/format_ltx.ts
index 35ca7b22f..33436ccee 100644
--- a/cli/format/format_ltx.ts
+++ b/cli/format/format_ltx.ts
@@ -49,6 +49,9 @@ async function formatLtxFile(file: string): Promise {
* Get list of static configs.
*/
async function getLtxConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectConfigs(acc: Array, it: TFolderFiles): Array {
if (Array.isArray(it)) {
it.forEach((nested) => collectConfigs(acc, nested));
diff --git a/cli/parse/parse_externals.ts b/cli/parse/parse_externals.ts
index 799ec5d93..a3a1c4985 100644
--- a/cli/parse/parse_externals.ts
+++ b/cli/parse/parse_externals.ts
@@ -47,6 +47,9 @@ export async function parseExternals(): Promise {
* Get list of LTX transformable descriptors.
*/
async function getSourcesList(source: string): Promise> {
+ /**
+ * todo;
+ */
function collectList(acc: Array, it: TFolderFiles): Array {
if (Array.isArray(it)) {
it.forEach((nested) => collectList(acc, nested));
diff --git a/cli/parse/utils/__test__/declaration.ts b/cli/parse/utils/__test__/declaration.ts
index 423659eca..e024a92cb 100644
--- a/cli/parse/utils/__test__/declaration.ts
+++ b/cli/parse/utils/__test__/declaration.ts
@@ -10,8 +10,14 @@ interface IAbstractInterface {
b: string;
}
+/**
+ * todo;
+ */
function extern(name: string, cb: (...args: Array) => void): void {}
+/**
+ * todo;
+ */
function another(name: string, cb: (...args: Array) => void): void {}
extern("module.callback_name_one", (a: number, b: string, c: boolean, d: SomeAlias): boolean => true);
diff --git a/cli/preview/preview.ts b/cli/preview/preview.ts
index 3072633e3..8267a8a55 100644
--- a/cli/preview/preview.ts
+++ b/cli/preview/preview.ts
@@ -98,7 +98,13 @@ function createFoldersForConfigs(xmlConfigs: Array
});
}
+/**
+ * todo;
+ */
async function getUiConfigs(filters: Array = []): Promise> {
+ /**
+ * todo;
+ */
function collectXmlConfigs(
acc: Array,
it: TFolderFiles
diff --git a/cli/preview/utils/generate_preview.ts b/cli/preview/utils/generate_preview.ts
index fa032a3cf..f103e2136 100644
--- a/cli/preview/utils/generate_preview.ts
+++ b/cli/preview/utils/generate_preview.ts
@@ -2,6 +2,9 @@ import { default as jsdom } from "jsdom";
const { style, STATIC_ASSET, GRADIENT_BG_, GENERIC } = generateDomClasses();
+/**
+ *
+ */
export function generateHTMLPreviewFromXMLString(content: string): string {
const dom = new jsdom.JSDOM(content);
@@ -58,10 +61,16 @@ export function generateHTMLPreviewFromXMLString(content: string): string {
return dom.serialize();
}
+/**
+ *
+ */
function prepareOther(node: HTMLElement): void {
node.style.border = "solid black 1px";
}
+/**
+ *
+ */
function prepareText(node: HTMLElement): void {
node.style.overflow = "hidden";
node.style.width = "100%";
@@ -74,6 +83,9 @@ function prepareText(node: HTMLElement): void {
}
}
+/**
+ *
+ */
function prepareTexture(node: HTMLElement): void {
node.setAttribute("texture_resource", node.textContent);
@@ -84,15 +96,24 @@ function prepareTexture(node: HTMLElement): void {
node.style.height = "100%";
}
+/**
+ *
+ */
function prepareWindow(node: HTMLElement): void {
node.style.position = "absolute";
node.style.background = "rgba(50, 50, 50, 0.05)";
}
+/**
+ *
+ */
function prepareStaticAsset(node: HTMLElement): void {
node.className = STATIC_ASSET + " " + GRADIENT_BG_ + Math.floor(Math.random() * 10);
}
+/**
+ *
+ */
function generateDomClasses() {
const GENERIC: string = "generic";
const STATIC_ASSET: string = "static-asset";
@@ -144,6 +165,9 @@ function generateDomClasses() {
};
}
+/**
+ * todo;
+ */
function getRandomColor(): string {
return "#" + (((1 << 24) * Math.random()) | 0).toString(16).padStart(6, "0");
}
diff --git a/cli/utils/fs/get_diffs.ts b/cli/utils/fs/get_diffs.ts
index 62aa4bab1..9500a11d4 100644
--- a/cli/utils/fs/get_diffs.ts
+++ b/cli/utils/fs/get_diffs.ts
@@ -31,10 +31,16 @@ export interface IDiffs {
deletions: IDiff;
}
+/**
+ * todo;
+ */
function getTime(dateOrDateStr: Date | string): number {
return typeof dateOrDateStr === "string" ? Date.parse(dateOrDateStr) : dateOrDateStr.getTime();
}
+/**
+ * todo;
+ */
async function ensureDirAccess(directory: string): Promise {
try {
await fsp.access(directory);
@@ -43,6 +49,11 @@ async function ensureDirAccess(directory: string): Promise {
}
}
+/**
+ * todo;
+ *
+ * @yields - files from directory in a recursive way
+ */
async function* getFiles(directory: string): AsyncGenerator {
const dirents = await fsp.readdir(directory, { withFileTypes: true });
@@ -54,6 +65,9 @@ async function* getFiles(directory: string): AsyncGenerator {
}
}
+/**
+ * todo;
+ */
async function getFileStats(directory: string, options): Promise {
const dir = path.resolve(directory);
@@ -85,6 +99,9 @@ async function getFileStats(directory: string, options): Promise {
return fileStats;
}
+/**
+ * todo;
+ */
export async function getDiffs(base: FilePathMap, target: FilePathMap, options?: DiffOptions): Promise {
const { exclusions = [], compareSizes = true } = options || {};
const statsOptions = { exclusions };
diff --git a/cli/utils/fs/open_folder_in_explorer.ts b/cli/utils/fs/open_folder_in_explorer.ts
index 8eb4ab1e9..740e0f8aa 100644
--- a/cli/utils/fs/open_folder_in_explorer.ts
+++ b/cli/utils/fs/open_folder_in_explorer.ts
@@ -1,6 +1,9 @@
import * as cp from "child_process";
import * as os from "os";
+/**
+ * todo;
+ */
export function openFolderInExplorer(path: string): Promise {
return new Promise((resolve, reject) => {
const osType: string = os.type();
diff --git a/cli/utils/fs/read_dir_content.ts b/cli/utils/fs/read_dir_content.ts
index 7736d12a7..1b0d01312 100644
--- a/cli/utils/fs/read_dir_content.ts
+++ b/cli/utils/fs/read_dir_content.ts
@@ -8,9 +8,7 @@ import { TDirectoryFilesTree } from "#/utils/fs/types";
*/
export async function readDirContent(dirPath: string): Promise {
return (await Promise.all(
- (
- await fs.readdir(dirPath, { withFileTypes: true })
- ).map(async (dirent) => {
+ (await fs.readdir(dirPath, { withFileTypes: true })).map(async (dirent) => {
const it = path.join(dirPath, dirent.name);
return dirent.isDirectory() ? await readDirContent(it) : it;
diff --git a/cli/utils/fs/read_dir_content_flat.ts b/cli/utils/fs/read_dir_content_flat.ts
index f49a63092..0ac7826b4 100644
--- a/cli/utils/fs/read_dir_content_flat.ts
+++ b/cli/utils/fs/read_dir_content_flat.ts
@@ -6,9 +6,7 @@ import * as path from "path";
*/
export async function readDirContentFlat(dirPath: string, container: Array = []): Promise> {
await Promise.all(
- (
- await fs.readdir(dirPath, { withFileTypes: true })
- ).map(async (dirent) => {
+ (await fs.readdir(dirPath, { withFileTypes: true })).map(async (dirent) => {
const it = path.join(dirPath, dirent.name);
if (dirent.isDirectory()) {
diff --git a/cli/utils/fs/read_dir_content_flat_gen.ts b/cli/utils/fs/read_dir_content_flat_gen.ts
index d59012cca..e6ff145cd 100644
--- a/cli/utils/fs/read_dir_content_flat_gen.ts
+++ b/cli/utils/fs/read_dir_content_flat_gen.ts
@@ -1,6 +1,12 @@
-import fsp from "fs/promises";
-import path from "path";
+import * as fsp from "fs/promises";
+import * as path from "path";
+/**
+ * Read folder content with generator.
+ *
+ * @param directory - target folder to traverse
+ * @yields next item in directory
+ */
export async function* readFolderGen(directory: string) {
const dirents = await fsp.readdir(directory, { withFileTypes: true });
diff --git a/cli/utils/fs/read_last_lines_of_file.ts b/cli/utils/fs/read_last_lines_of_file.ts
index 8fa6f2c9c..e2a7d7f52 100644
--- a/cli/utils/fs/read_last_lines_of_file.ts
+++ b/cli/utils/fs/read_last_lines_of_file.ts
@@ -6,6 +6,9 @@ import { Optional } from "#/utils/types";
const NEW_LINE_CHARACTERS: Array = ["\n"];
+/**
+ * todo;
+ */
export async function readLastLinesOfFile(
filePath: string,
maxLineCount: number,
diff --git a/doc/BUILDING_CUSTOM_GAME_PACKAGE.md b/doc/BUILDING_CUSTOM_GAME_PACKAGE.md
index b9fa375b0..9a7a0816f 100644
--- a/doc/BUILDING_CUSTOM_GAME_PACKAGE.md
+++ b/doc/BUILDING_CUSTOM_GAME_PACKAGE.md
@@ -10,7 +10,7 @@ and bundled together with custom engine.
Comparing to normal gamedata builds the only needed thing is full assets list.
To build package you will need [extended](https://gitlab.com/xray-forge/stalker-xrf-resources-extended) assets
-and one of locales packs, for example [en](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-en).
+and one of locales packs, for example [eng](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng).
After cloning suggested repositories or providing custom assets, you should list them in 'config.json' if paths are different from already suggested.
@@ -19,10 +19,10 @@ After cloning suggested repositories or providing custom assets, you should list
If assets are downloaded and configured correctly, the only needed thing is:
```
-npm run cli pack game -- --clean --build --optimize
+npm run cli pack game -- --clean --optimize
# or
-npm run cli pack game -- -c -b -o
+npm run cli pack game -- -c -o
# or
npm run pack:game
diff --git a/doc/TODO.md b/doc/TODO.md
index ad314d575..53eda9ba9 100644
--- a/doc/TODO.md
+++ b/doc/TODO.md
@@ -13,6 +13,7 @@
## 🧰 Requests to open x-ray
+- Add callback notifying about game save to get filename
- With lua bindings generation include all call overrides when output TXT
- Export actor menu and actor menu item classes for overriding with lua
- Fix numerous calls to disk with menu, implement caching for character menu and fix lags when opening inventory
diff --git a/package-lock.json b/package-lock.json
index e4ab870d1..8ab1b7bf2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,11 +21,12 @@
"@typescript-eslint/parser": "^5.59.11",
"@typescript-to-lua/language-extensions": "1.0.0",
"chalk": "4.1.2",
- "commander": "^10.0.1",
- "eslint": "^8.43.0",
- "eslint-config-standard-with-typescript": "^35.0.0",
+ "commander": "^11.0.0",
+ "eslint": "^8.44.0",
+ "eslint-config-standard-with-typescript": "^36.0.0",
"eslint-plugin-import": "^2.27.5",
- "eslint-plugin-jest": "^27.2.1",
+ "eslint-plugin-jest": "^27.2.2",
+ "eslint-plugin-jsdoc": "^46.4.3",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"fast-xml-parser": "^4.2.4",
"fengari": "0.1.4",
@@ -34,13 +35,22 @@
"jsdom": "^22.1.0",
"jsx-xml": "^0.2.3",
"lua-types": "^2.13.1",
- "prettier": "^2.8.8",
+ "prettier": "^3.0.0",
"steam-path": "^1.0.2",
"ts-jest": "^29.1.0",
"ts-node": "10.9.1",
"tsconfig-paths": "^4.2.0",
- "typescript": "^5.1.3",
- "typescript-to-lua": "^1.16.2"
+ "typescript": "^5.1.6",
+ "typescript-to-lua": "^1.16.3"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -693,6 +703,20 @@
"node": ">=12"
}
},
+ "node_modules/@es-joy/jsdoccomment": {
+ "version": "0.39.4",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz",
+ "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==",
+ "dev": true,
+ "dependencies": {
+ "comment-parser": "1.3.1",
+ "esquery": "^1.5.0",
+ "jsdoc-type-pratt-parser": "~4.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz",
@@ -718,14 +742,14 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
- "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
+ "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.5.2",
+ "espree": "^9.6.0",
"globals": "^13.19.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
@@ -741,9 +765,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.43.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
- "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+ "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1711,9 +1735,9 @@
"dev": true
},
"node_modules/acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -1838,6 +1862,15 @@
"node": ">= 8"
}
},
+ "node_modules/are-docs-informative": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
+ "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -2094,6 +2127,18 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
+ "node_modules/builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/builtins": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
@@ -2258,12 +2303,21 @@
}
},
"node_modules/commander": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
- "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz",
+ "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==",
"dev": true,
"engines": {
- "node": ">=14"
+ "node": ">=16"
+ }
+ },
+ "node_modules/comment-parser": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz",
+ "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12.0.0"
}
},
"node_modules/concat-map": {
@@ -2607,15 +2661,15 @@
}
},
"node_modules/eslint": {
- "version": "8.43.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
- "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
+ "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.0.3",
- "@eslint/js": "8.43.0",
+ "@eslint/eslintrc": "^2.1.0",
+ "@eslint/js": "8.44.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@@ -2627,7 +2681,7 @@
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^7.2.0",
"eslint-visitor-keys": "^3.4.1",
- "espree": "^9.5.2",
+ "espree": "^9.6.0",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -2647,7 +2701,7 @@
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
+ "optionator": "^0.9.3",
"strip-ansi": "^6.0.1",
"strip-json-comments": "^3.1.0",
"text-table": "^0.2.0"
@@ -2689,9 +2743,9 @@
}
},
"node_modules/eslint-config-standard-with-typescript": {
- "version": "35.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-35.0.0.tgz",
- "integrity": "sha512-Xa7DY9GgduZyp0qmXxBF0/dB+Vm4/DgWu1lGpNLJV2d46aCaUxTKDEnkzjUWX/1O9S0a+Dhnw7A4oI0JpYzwtw==",
+ "version": "36.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-36.0.0.tgz",
+ "integrity": "sha512-8ZSEskfrDAkUF2lTQLMT0CBzgRNlx1uIM7l2I7L683dKAXUdHuEL2x+GxuGAsdsoWbx7W7Zv0xF67VCEZXIk0Q==",
"dev": true,
"dependencies": {
"@typescript-eslint/parser": "^5.50.0",
@@ -2882,9 +2936,9 @@
}
},
"node_modules/eslint-plugin-jest": {
- "version": "27.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz",
- "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz",
+ "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "^5.10.0"
@@ -2894,7 +2948,8 @@
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": "^5.0.0",
- "eslint": "^7.0.0 || ^8.0.0"
+ "eslint": "^7.0.0 || ^8.0.0",
+ "jest": "*"
},
"peerDependenciesMeta": {
"@typescript-eslint/eslint-plugin": {
@@ -2905,6 +2960,29 @@
}
}
},
+ "node_modules/eslint-plugin-jsdoc": {
+ "version": "46.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.3.tgz",
+ "integrity": "sha512-Prc7ol+vCIghPeECpwZq5+P+VZfoi87suywvbYCiCnkI1kTmVSdcOC2M8mioglWxBbd28wbb1OVjg/8OzGzatA==",
+ "dev": true,
+ "dependencies": {
+ "@es-joy/jsdoccomment": "~0.39.4",
+ "are-docs-informative": "^0.0.2",
+ "comment-parser": "1.3.1",
+ "debug": "^4.3.4",
+ "escape-string-regexp": "^4.0.0",
+ "esquery": "^1.5.0",
+ "is-builtin-module": "^3.2.1",
+ "semver": "^7.5.1",
+ "spdx-expression-parse": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/eslint-plugin-n": {
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.6.0.tgz",
@@ -3052,12 +3130,12 @@
}
},
"node_modules/espree": {
- "version": "9.5.2",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
- "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
+ "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
"dev": true,
"dependencies": {
- "acorn": "^8.8.0",
+ "acorn": "^8.9.0",
"acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.4.1"
},
@@ -3824,6 +3902,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-builtin-module": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
+ "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
+ "dev": true,
+ "dependencies": {
+ "builtin-modules": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -4716,6 +4809,15 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsdoc-type-pratt-parser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
+ "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/jsdom": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
@@ -5175,17 +5277,17 @@
}
},
"node_modules/optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
"dev": true,
"dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
+ "type-check": "^0.4.0"
},
"engines": {
"node": ">= 0.8.0"
@@ -5424,15 +5526,15 @@
}
},
"node_modules/prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"dev": true,
"bin": {
- "prettier": "bin-prettier.js"
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
@@ -5770,9 +5872,9 @@
}
},
"node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@@ -5880,6 +5982,28 @@
"node": ">=0.10.0"
}
},
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.13",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
+ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
+ "dev": true
+ },
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -6322,9 +6446,9 @@
}
},
"node_modules/typescript": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz",
- "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+ "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -6335,9 +6459,9 @@
}
},
"node_modules/typescript-to-lua": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.16.2.tgz",
- "integrity": "sha512-QtkQCDMNWMVilw/MsgIMLEVKYmSXvTgM21Li77KKKOyDJ+sSxph2oJfQ8XvXI3X6sse9VZhYC7gKLWi7qHKr7w==",
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.16.3.tgz",
+ "integrity": "sha512-vWJIfupLO6u22tMYmlczdcb5TtFUv8Mwf79ZKUyxqX4td5xWv3L2wu5WCx0YrOZ4//JwDQohrkfX1y4LbZTugQ==",
"dev": true,
"dependencies": {
"@typescript-to-lua/language-extensions": "1.0.0",
@@ -6567,15 +6691,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -6792,6 +6907,21 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "src/typedefs/xray16/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"src/typedefs/xray16/node_modules/typedoc": {
"version": "0.23.26",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.26.tgz",
@@ -6828,6 +6958,12 @@
}
},
"dependencies": {
+ "@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true
+ },
"@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
@@ -7328,6 +7464,17 @@
"@jridgewell/trace-mapping": "0.3.9"
}
},
+ "@es-joy/jsdoccomment": {
+ "version": "0.39.4",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz",
+ "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==",
+ "dev": true,
+ "requires": {
+ "comment-parser": "1.3.1",
+ "esquery": "^1.5.0",
+ "jsdoc-type-pratt-parser": "~4.0.0"
+ }
+ },
"@eslint-community/eslint-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz",
@@ -7344,14 +7491,14 @@
"dev": true
},
"@eslint/eslintrc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
- "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
+ "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.5.2",
+ "espree": "^9.6.0",
"globals": "^13.19.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
@@ -7361,9 +7508,9 @@
}
},
"@eslint/js": {
- "version": "8.43.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
- "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+ "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
"dev": true
},
"@humanwhocodes/config-array": {
@@ -8124,9 +8271,9 @@
"dev": true
},
"acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
"dev": true
},
"acorn-jsx": {
@@ -8211,6 +8358,12 @@
"picomatch": "^2.0.4"
}
},
+ "are-docs-informative": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
+ "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
+ "dev": true
+ },
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -8403,6 +8556,12 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
+ "builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true
+ },
"builtins": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
@@ -8517,9 +8676,15 @@
}
},
"commander": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
- "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz",
+ "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==",
+ "dev": true
+ },
+ "comment-parser": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz",
+ "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==",
"dev": true
},
"concat-map": {
@@ -8780,15 +8945,15 @@
"dev": true
},
"eslint": {
- "version": "8.43.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
- "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
+ "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
"dev": true,
"requires": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.0.3",
- "@eslint/js": "8.43.0",
+ "@eslint/eslintrc": "^2.1.0",
+ "@eslint/js": "8.44.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@@ -8800,7 +8965,7 @@
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^7.2.0",
"eslint-visitor-keys": "^3.4.1",
- "espree": "^9.5.2",
+ "espree": "^9.6.0",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -8820,7 +8985,7 @@
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
+ "optionator": "^0.9.3",
"strip-ansi": "^6.0.1",
"strip-json-comments": "^3.1.0",
"text-table": "^0.2.0"
@@ -8834,9 +8999,9 @@
"requires": {}
},
"eslint-config-standard-with-typescript": {
- "version": "35.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-35.0.0.tgz",
- "integrity": "sha512-Xa7DY9GgduZyp0qmXxBF0/dB+Vm4/DgWu1lGpNLJV2d46aCaUxTKDEnkzjUWX/1O9S0a+Dhnw7A4oI0JpYzwtw==",
+ "version": "36.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-36.0.0.tgz",
+ "integrity": "sha512-8ZSEskfrDAkUF2lTQLMT0CBzgRNlx1uIM7l2I7L683dKAXUdHuEL2x+GxuGAsdsoWbx7W7Zv0xF67VCEZXIk0Q==",
"dev": true,
"requires": {
"@typescript-eslint/parser": "^5.50.0",
@@ -8986,14 +9151,31 @@
}
},
"eslint-plugin-jest": {
- "version": "27.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz",
- "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz",
+ "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "^5.10.0"
}
},
+ "eslint-plugin-jsdoc": {
+ "version": "46.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.3.tgz",
+ "integrity": "sha512-Prc7ol+vCIghPeECpwZq5+P+VZfoi87suywvbYCiCnkI1kTmVSdcOC2M8mioglWxBbd28wbb1OVjg/8OzGzatA==",
+ "dev": true,
+ "requires": {
+ "@es-joy/jsdoccomment": "~0.39.4",
+ "are-docs-informative": "^0.0.2",
+ "comment-parser": "1.3.1",
+ "debug": "^4.3.4",
+ "escape-string-regexp": "^4.0.0",
+ "esquery": "^1.5.0",
+ "is-builtin-module": "^3.2.1",
+ "semver": "^7.5.1",
+ "spdx-expression-parse": "^3.0.1"
+ }
+ },
"eslint-plugin-n": {
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.6.0.tgz",
@@ -9092,12 +9274,12 @@
"dev": true
},
"espree": {
- "version": "9.5.2",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
- "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
+ "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
"dev": true,
"requires": {
- "acorn": "^8.8.0",
+ "acorn": "^8.9.0",
"acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.4.1"
}
@@ -9658,6 +9840,15 @@
"has-tostringtag": "^1.0.0"
}
},
+ "is-builtin-module": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
+ "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "^3.3.0"
+ }
+ },
"is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -10325,6 +10516,12 @@
"argparse": "^2.0.1"
}
},
+ "jsdoc-type-pratt-parser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
+ "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
+ "dev": true
+ },
"jsdom": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
@@ -10679,17 +10876,17 @@
}
},
"optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
"dev": true,
"requires": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
+ "type-check": "^0.4.0"
}
},
"os-tmpdir": {
@@ -10855,9 +11052,9 @@
"dev": true
},
"prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"dev": true
},
"pretty-format": {
@@ -11088,9 +11285,9 @@
}
},
"semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
@@ -11176,6 +11373,28 @@
}
}
},
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.13",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
+ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
+ "dev": true
+ },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -11487,15 +11706,15 @@
"dev": true
},
"typescript": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz",
- "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+ "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
"dev": true
},
"typescript-to-lua": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.16.2.tgz",
- "integrity": "sha512-QtkQCDMNWMVilw/MsgIMLEVKYmSXvTgM21Li77KKKOyDJ+sSxph2oJfQ8XvXI3X6sse9VZhYC7gKLWi7qHKr7w==",
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-1.16.3.tgz",
+ "integrity": "sha512-vWJIfupLO6u22tMYmlczdcb5TtFUv8Mwf79ZKUyxqX4td5xWv3L2wu5WCx0YrOZ4//JwDQohrkfX1y4LbZTugQ==",
"dev": true,
"requires": {
"@typescript-to-lua/language-extensions": "1.0.0",
@@ -11669,12 +11888,6 @@
"is-symbol": "^1.0.3"
}
},
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true
- },
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -11771,6 +11984,12 @@
"brace-expansion": "^2.0.1"
}
},
+ "prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true
+ },
"typedoc": {
"version": "0.23.26",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.26.tgz",
diff --git a/package.json b/package.json
index 6f80de6cf..3509594cc 100644
--- a/package.json
+++ b/package.json
@@ -29,11 +29,12 @@
"@typescript-eslint/parser": "^5.59.11",
"@typescript-to-lua/language-extensions": "1.0.0",
"chalk": "4.1.2",
- "commander": "^10.0.1",
- "eslint": "^8.43.0",
- "eslint-config-standard-with-typescript": "^35.0.0",
+ "commander": "^11.0.0",
+ "eslint": "^8.44.0",
+ "eslint-config-standard-with-typescript": "^36.0.0",
"eslint-plugin-import": "^2.27.5",
- "eslint-plugin-jest": "^27.2.1",
+ "eslint-plugin-jest": "^27.2.2",
+ "eslint-plugin-jsdoc": "^46.4.3",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"fast-xml-parser": "^4.2.4",
"fengari": "0.1.4",
@@ -42,13 +43,13 @@
"jsdom": "^22.1.0",
"jsx-xml": "^0.2.3",
"lua-types": "^2.13.1",
- "prettier": "^2.8.8",
+ "prettier": "^3.0.0",
"steam-path": "^1.0.2",
"ts-jest": "^29.1.0",
"ts-node": "10.9.1",
"tsconfig-paths": "^4.2.0",
- "typescript": "^5.1.3",
- "typescript-to-lua": "^1.16.2"
+ "typescript": "^5.1.6",
+ "typescript-to-lua": "^1.16.3"
},
"bin": {
"xrf": "./cli/run.ts"
diff --git a/src/engine/core/database/offline.ts b/src/engine/core/database/offline.ts
index 16a60006a..f22d884b0 100644
--- a/src/engine/core/database/offline.ts
+++ b/src/engine/core/database/offline.ts
@@ -30,10 +30,6 @@ export function registerOfflineObject(
/**
* Hard reset offline object state.
* Create new representation entry if it was not initialize before.
- *
- * @param objectId - game object ID to register offline representation
- * @param state - base offline state to register
- * @returns stored offline object state representation
*/
export function hardResetOfflineObject(
objectId: TNumberId,
@@ -48,10 +44,6 @@ export function hardResetOfflineObject(
/**
* Soft reset offline object state.
* Do not create new representation entry if it was not initialize before.
- *
- * @param objectId - game object ID to register offline representation
- * @param state - base offline state to register
- * @returns stored offline object state representation
*/
export function softResetOfflineObject(
objectId: TNumberId,
diff --git a/src/engine/core/database/save_markers.ts b/src/engine/core/database/save_markers.ts
index ebb6c58d5..8281fc715 100644
--- a/src/engine/core/database/save_markers.ts
+++ b/src/engine/core/database/save_markers.ts
@@ -14,7 +14,7 @@ const logger: LuaLogger = new LuaLogger($filename);
export function openSaveMarker(packet: NetPacket, markerName: TName): void {
const packetSize: TCount = packet.w_tell();
- assert(packetSize < 20_480, "You are saving too much in '%s' - '%s'.", markerName, packetSize);
+ assert(packetSize < 16_384, "You are saving too much in '%s' - '%s'.", markerName, packetSize);
registry.saveMarkers.set(markerName, packet.w_tell());
}
diff --git a/src/engine/core/managers/base/SaveManager.test.ts b/src/engine/core/managers/base/SaveManager.test.ts
index 4fe5e3b22..28b7d3c9f 100644
--- a/src/engine/core/managers/base/SaveManager.test.ts
+++ b/src/engine/core/managers/base/SaveManager.test.ts
@@ -1,6 +1,7 @@
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import { disposeManagers, initializeManager, registerActor, registry } from "@/engine/core/database";
+import { EGameEvent, EventsManager } from "@/engine/core/managers";
import { TAbstractCoreManagerConstructor } from "@/engine/core/managers/base/AbstractCoreManager";
import { SaveManager } from "@/engine/core/managers/base/SaveManager";
import { AchievementsManager } from "@/engine/core/managers/interaction/achievements";
@@ -16,8 +17,9 @@ import { SurgeManager } from "@/engine/core/managers/world/SurgeManager";
import { TreasureManager } from "@/engine/core/managers/world/TreasureManager";
import { WeatherManager } from "@/engine/core/managers/world/WeatherManager";
import { AnyObject } from "@/engine/lib/types";
-import { mockClientGameObject } from "@/fixtures/xray";
-import { mockNetPacket } from "@/fixtures/xray/mocks/save";
+import { MockIoFile } from "@/fixtures/lua";
+import { resetFunctionMock } from "@/fixtures/utils";
+import { mockClientGameObject, mockNetPacket } from "@/fixtures/xray";
describe("SaveManager class", () => {
const mockLifecycleMethods = () => {
@@ -38,9 +40,10 @@ describe("SaveManager class", () => {
beforeEach(() => {
disposeManagers();
+ resetFunctionMock(io.open);
});
- it("Should save and load data from managers in a strict order", () => {
+ it("should save and load data from managers in a strict order", () => {
const expectedOrder: Array = [
WeatherManager,
ReleaseBodyManager,
@@ -62,18 +65,18 @@ describe("SaveManager class", () => {
expect(saveOrder).toEqual([]);
expect(loadOrder).toEqual([]);
- SaveManager.getInstance().save(mockNetPacket());
+ SaveManager.getInstance().clientSave(mockNetPacket());
expect(saveOrder).toEqual(expectedOrder);
expect(loadOrder).toEqual([]);
- SaveManager.getInstance().load(mockNetPacket());
+ SaveManager.getInstance().clientLoad(mockNetPacket());
expect(saveOrder).toEqual(expectedOrder);
expect(loadOrder).toEqual(expectedOrder);
});
- it("Should read and write data from managers in a strict order", () => {
+ it("should read and write data from managers in a strict order", () => {
registerActor(mockClientGameObject());
const expectedOrder: Array = [SimulationBoardManager];
@@ -85,14 +88,85 @@ describe("SaveManager class", () => {
expect(saveOrder).toEqual([]);
expect(loadOrder).toEqual([]);
- SaveManager.getInstance().writeState(mockNetPacket());
+ SaveManager.getInstance().serverSave(mockNetPacket());
expect(saveOrder).toEqual(expectedOrder);
expect(loadOrder).toEqual([]);
- SaveManager.getInstance().readState(mockNetPacket());
+ SaveManager.getInstance().serverLoad(mockNetPacket());
expect(saveOrder).toEqual(expectedOrder);
expect(loadOrder).toEqual(expectedOrder);
});
+
+ it("should have implementation base for save callbacks", () => {
+ const saveManager: SaveManager = SaveManager.getInstance();
+
+ expect(saveManager.onBeforeGameSave).toBeDefined();
+ expect(saveManager.onGameSave).toBeDefined();
+ expect(saveManager.onBeforeGameLoad).toBeDefined();
+ expect(saveManager.onGameLoad).toBeDefined();
+ });
+
+ it("should properly create dynamic saves", () => {
+ const saveManager: SaveManager = SaveManager.getInstance();
+ const file: MockIoFile = new MockIoFile("test", "wb");
+
+ const onSave = jest.fn((data: AnyObject) => {
+ data.example = 123;
+ });
+
+ EventsManager.getInstance().registerCallback(EGameEvent.GAME_SAVE, onSave);
+
+ jest.spyOn(io, "open").mockImplementationOnce(() => $multi(file.asMock()));
+
+ saveManager.onBeforeGameSave("test.scop");
+
+ expect(onSave).toHaveBeenCalledTimes(1);
+ expect(io.open).toHaveBeenCalledWith("$game_saves$test.scopx", "wb");
+ expect(file.write).toHaveBeenCalledWith(JSON.stringify({ generic: { example: 123 }, store: {} }));
+ expect(file.close).toHaveBeenCalledTimes(1);
+ });
+
+ it("should properly load dynamic saves", () => {
+ const saveManager: SaveManager = SaveManager.getInstance();
+ const file: MockIoFile = new MockIoFile("test", "wb");
+
+ file.content = JSON.stringify({ generic: { example: 123 }, store: {} });
+
+ const onLoad = jest.fn((data: AnyObject) => {
+ expect(data).toEqual({ example: 123 });
+ });
+
+ EventsManager.getInstance().registerCallback(EGameEvent.GAME_LOAD, onLoad);
+
+ jest.spyOn(io, "open").mockImplementation(() => $multi(file.asMock()));
+
+ const contentBefore: AnyObject = saveManager.dynamicData;
+
+ saveManager.onBeforeGameLoad("F:\\\\parent\\\\test.scop");
+
+ expect(marshal.decode).toHaveBeenCalledWith(file.content);
+ expect(onLoad).toHaveBeenCalledTimes(1);
+ expect(io.open).toHaveBeenCalledWith("F:\\\\parent\\\\test.scopx", "rb");
+ expect(file.read).toHaveBeenCalledTimes(1);
+ expect(file.close).toHaveBeenCalledTimes(1);
+ expect(contentBefore).not.toBe(saveManager.dynamicData);
+
+ // In case of empty file data should stay same.
+ const contentAfter: AnyObject = saveManager.dynamicData;
+
+ file.content = "";
+ saveManager.onBeforeGameLoad("F:\\\\parent\\\\test.scop");
+ expect(contentAfter).toBe(saveManager.dynamicData);
+
+ file.content = null;
+ saveManager.onBeforeGameLoad("F:\\\\parent\\\\test.scop");
+ expect(contentAfter).toBe(saveManager.dynamicData);
+
+ file.content = "{}";
+ file.isOpen = false;
+ saveManager.onBeforeGameLoad("F:\\\\parent\\\\test.scop");
+ expect(contentAfter).toBe(saveManager.dynamicData);
+ });
});
diff --git a/src/engine/core/managers/base/SaveManager.ts b/src/engine/core/managers/base/SaveManager.ts
index 1dad527e9..d78dbf908 100644
--- a/src/engine/core/managers/base/SaveManager.ts
+++ b/src/engine/core/managers/base/SaveManager.ts
@@ -1,3 +1,4 @@
+import { EGameEvent, EventsManager } from "@/engine/core/managers";
import { AbstractCoreManager } from "@/engine/core/managers/base/AbstractCoreManager";
import { AchievementsManager } from "@/engine/core/managers/interaction/achievements";
import { SimulationBoardManager } from "@/engine/core/managers/interaction/SimulationBoardManager";
@@ -11,20 +12,28 @@ import { ReleaseBodyManager } from "@/engine/core/managers/world/ReleaseBodyMana
import { SurgeManager } from "@/engine/core/managers/world/SurgeManager";
import { TreasureManager } from "@/engine/core/managers/world/TreasureManager";
import { WeatherManager } from "@/engine/core/managers/world/WeatherManager";
+import { loadDynamicGameSave, saveDynamicGameSave } from "@/engine/core/utils/game";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { NetPacket, NetProcessor } from "@/engine/lib/types";
+import { AnyObject, NetPacket, NetProcessor, Optional, TName } from "@/engine/lib/types";
const logger: LuaLogger = new LuaLogger($filename);
+export interface IDynamicSaveData {
+ generic: AnyObject;
+ store: AnyObject;
+}
+
/**
* Manage game saves for other managers / parts.
*/
export class SaveManager extends AbstractCoreManager {
+ public dynamicData: IDynamicSaveData = { generic: {}, store: {} };
+
/**
* Save core managers data.
*/
- public override save(packet: NetPacket): void {
- logger.info("Saving");
+ public clientSave(packet: NetPacket): void {
+ logger.info("Saving client");
WeatherManager.getInstance().save(packet);
ReleaseBodyManager.getInstance().save(packet);
@@ -42,8 +51,8 @@ export class SaveManager extends AbstractCoreManager {
/**
* Load core managers data.
*/
- public override load(reader: NetProcessor): void {
- logger.info("Loading");
+ public clientLoad(reader: NetProcessor): void {
+ logger.info("Loading client");
WeatherManager.getInstance().load(reader);
ReleaseBodyManager.getInstance().load(reader);
@@ -61,14 +70,64 @@ export class SaveManager extends AbstractCoreManager {
/**
* Write state for core managers.
*/
- public writeState(packet: NetPacket): void {
+ public serverSave(packet: NetPacket): void {
+ logger.info("Saving server");
+
SimulationBoardManager.getInstance().save(packet);
}
/**
* Read state for core managers.
*/
- public readState(reader: NetProcessor): void {
+ public serverLoad(reader: NetProcessor): void {
+ logger.info("Loading server");
+
SimulationBoardManager.getInstance().load(reader);
}
+
+ /**
+ * When game save creation starting.
+ *
+ * @param saveName - name of save file, just base name with extension like `example.scop`
+ */
+ public onBeforeGameSave(saveName: TName): void {
+ logger.info("Before game save:", saveName);
+
+ EventsManager.getInstance().emitEvent(EGameEvent.GAME_SAVE, this.dynamicData.generic);
+
+ saveDynamicGameSave(saveName, this.dynamicData);
+ }
+
+ /**
+ * When game saved successfully.
+ *
+ * @param saveName - name of save file, just base name with extension like `example.scop`
+ */
+ public onGameSave(saveName: TName): void {
+ logger.info("On game save:", saveName);
+ }
+
+ /**
+ * When game save loading starts.
+ *
+ * @param saveName - name of save file, full path with disk/system folders structure
+ */
+ public onBeforeGameLoad(saveName: TName): void {
+ logger.info("Before game load:", saveName);
+
+ const data: Optional = loadDynamicGameSave(saveName);
+
+ this.dynamicData = data ? data : this.dynamicData;
+
+ EventsManager.getInstance().emitEvent(EGameEvent.GAME_LOAD, this.dynamicData.generic);
+ }
+
+ /**
+ * When game save loaded successfully.
+ *
+ * @param saveName - name of save file, full path with disk/system folders structure
+ */
+ public onGameLoad(saveName: TName): void {
+ logger.info("On game load:", saveName);
+ }
}
diff --git a/src/engine/core/managers/events/EventsManager.test.ts b/src/engine/core/managers/events/EventsManager.test.ts
index dc81d4aa9..ccd293144 100644
--- a/src/engine/core/managers/events/EventsManager.test.ts
+++ b/src/engine/core/managers/events/EventsManager.test.ts
@@ -13,7 +13,7 @@ describe("EventsManager class", () => {
it("should correctly initialize", () => {
const manager: EventsManager = getManagerInstance(EventsManager);
- expect(MockLuaTable.getMockSize(manager.callbacks)).toBe(29);
+ expect(MockLuaTable.getMockSize(manager.callbacks)).toBe(31);
Object.keys(manager.callbacks).forEach((it) => {
expect(MockLuaTable.getMockSize(manager.callbacks[it as unknown as EGameEvent])).toBe(0);
diff --git a/src/engine/core/managers/events/types.ts b/src/engine/core/managers/events/types.ts
index d716dd411..ad63479ff 100644
--- a/src/engine/core/managers/events/types.ts
+++ b/src/engine/core/managers/events/types.ts
@@ -120,6 +120,14 @@ export enum EGameEvent {
* Game started.
*/
GAME_STARTED,
+ /**
+ * Game state save.
+ */
+ GAME_SAVE,
+ /**
+ * Game state load.
+ */
+ GAME_LOAD,
}
/**
diff --git a/src/engine/core/managers/interaction/SimulationBoardManager.ts b/src/engine/core/managers/interaction/SimulationBoardManager.ts
index 6a0ace681..0ad1ec4f8 100644
--- a/src/engine/core/managers/interaction/SimulationBoardManager.ts
+++ b/src/engine/core/managers/interaction/SimulationBoardManager.ts
@@ -303,8 +303,10 @@ export class SimulationBoardManager extends AbstractCoreManager {
}
if (oldSmartTerrainId !== null && this.smartTerrains.has(oldSmartTerrainId)) {
+ const smartTerrain: SmartTerrain = this.smartTerrains.get(oldSmartTerrainId).smartTerrain;
+
this.smartTerrains.get(oldSmartTerrainId).assignedSquads.delete(squad.id);
- this.smartTerrains.get(oldSmartTerrainId).smartTerrain.updateMapDisplay();
+ smartTerrain.mapDisplayManager.updateSmartTerrainMapSpot(smartTerrain);
}
if (smartTerrainId === null) {
@@ -317,7 +319,7 @@ export class SimulationBoardManager extends AbstractCoreManager {
squad.assignSmartTerrain(target.smartTerrain);
target.assignedSquads.set(squad.id, squad);
- target.smartTerrain.updateMapDisplay();
+ target.smartTerrain.mapDisplayManager.updateSmartTerrainMapSpot(target.smartTerrain);
}
/**
diff --git a/src/engine/core/managers/interaction/tasks/types.ts b/src/engine/core/managers/interaction/tasks/types.ts
index fe04a5c6f..0ec56cdfa 100644
--- a/src/engine/core/managers/interaction/tasks/types.ts
+++ b/src/engine/core/managers/interaction/tasks/types.ts
@@ -21,8 +21,11 @@ export enum ETaskStatus {
/**
* Set of possible task states, where key is state and value is true / null.
*/
-export const POSSIBLE_STATES: Record = Object.values(ETaskState).reduce((acc, it) => {
- acc[it] = true;
+export const POSSIBLE_STATES: Record = Object.values(ETaskState).reduce(
+ (acc, it) => {
+ acc[it] = true;
- return acc;
-}, {} as Record);
+ return acc;
+ },
+ {} as Record
+);
diff --git a/src/engine/core/managers/interface/MapDisplayManager.ts b/src/engine/core/managers/interface/MapDisplayManager.ts
index 04431fb28..f1334cfa1 100644
--- a/src/engine/core/managers/interface/MapDisplayManager.ts
+++ b/src/engine/core/managers/interface/MapDisplayManager.ts
@@ -9,10 +9,18 @@ import {
primaryMapSpotObjects,
sleepZones,
} from "@/engine/core/managers/interface/MapDisplayManagerObjects";
+import { SmartTerrain, Squad } from "@/engine/core/objects";
import { parseConditionsList, pickSectionFromCondList, readIniString, TConditionList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { anomalyHasArtefact } from "@/engine/core/utils/object/object_anomaly";
+import { isSquadMonsterCommunity } from "@/engine/core/utils/object";
+import { getAnomalyArtefacts } from "@/engine/core/utils/object/object_anomaly";
import { hasAlifeInfo } from "@/engine/core/utils/object/object_info_portion";
+import {
+ ERelation,
+ getSquadMembersRelationToActor,
+ getSquadMembersRelationToActorSafe,
+} from "@/engine/core/utils/relation";
+import { gameConfig } from "@/engine/lib/configs/GameConfig";
import { captions } from "@/engine/lib/constants/captions/captions";
import { infoPortions } from "@/engine/lib/constants/info_portions/info_portions";
import { levels } from "@/engine/lib/constants/levels";
@@ -22,12 +30,14 @@ import {
AlifeSimulator,
ClientObject,
EScheme,
+ LuaArray,
Maybe,
Optional,
ServerObject,
TDistance,
TDuration,
TLabel,
+ TName,
TNumberId,
TSection,
TTimestamp,
@@ -37,11 +47,11 @@ import {
const logger: LuaLogger = new LuaLogger($filename);
/**
- * todo;
+ * Manager handling display of objects on game map in PDA.
*/
export class MapDisplayManager extends AbstractCoreManager {
public static readonly DISTANCE_TO_SHOW_MAP_MARKS: TDistance = 75;
- public static readonly UPDATES_THROTTLE: TDuration = 10_000;
+ public static readonly UPDATES_THROTTLE: TDuration = 5_000;
public isInitialized: boolean = false;
public lastUpdateAt: TTimestamp = 0;
@@ -59,7 +69,12 @@ export class MapDisplayManager extends AbstractCoreManager {
}
/**
- * todo: Description.
+ * Update map display for game object.
+ *
+ * @param object - target client object
+ * @param scheme - active logic scheme
+ * @param state - target object registry state
+ * @param section - active logic section
*/
public updateObjectMapSpot(
object: ClientObject,
@@ -135,7 +150,10 @@ export class MapDisplayManager extends AbstractCoreManager {
}
/**
- * todo: Description.
+ * Remove object map spot display.
+ *
+ * @param object - target client object
+ * @param state - target object registry state
*/
public removeObjectMapSpot(object: ClientObject, state: IRegistryObjectState): void {
logger.info("Remove object spot:", object.name());
@@ -176,6 +194,183 @@ export class MapDisplayManager extends AbstractCoreManager {
}
}
+ /**
+ * Update map spot for squad.
+ *
+ * @param squad - target squad server object
+ */
+ public updateSquadMapSpot(squad: Squad): void {
+ const squadCommanderId: TNumberId = squad.commander_id();
+
+ if (squad.isMapDisplayHidden || squadCommanderId === null) {
+ return this.removeSquadMapSpot(squad);
+ }
+
+ if (squad.currentMapSpotId !== squadCommanderId) {
+ this.removeSquadMapSpot(squad);
+ squad.currentMapSpotId = squadCommanderId;
+ this.updateSquadMapSpot(squad);
+
+ return;
+ }
+
+ if (
+ level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_trader_location) !== 0 ||
+ level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_mechanic_location) !== 0 ||
+ level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_scout_location) !== 0 ||
+ level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_quest_npc_location) !== 0 ||
+ level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_medic_location) !== 0
+ ) {
+ squad.isMapDisplayHidden = true;
+
+ return;
+ }
+
+ let spot: Optional = null;
+
+ /**
+ * In case of debug use map display like in clear sky.
+ */
+ if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
+ if (isSquadMonsterCommunity(squad.faction)) {
+ spot = mapMarks.alife_presentation_squad_monster_debug;
+ } else {
+ const relation: ERelation = getSquadMembersRelationToActorSafe(squad);
+
+ switch (relation) {
+ case ERelation.FRIEND:
+ spot = mapMarks.alife_presentation_squad_friend_debug;
+ break;
+ case ERelation.NEUTRAL:
+ spot = mapMarks.alife_presentation_squad_neutral_debug;
+ break;
+ case ERelation.ENEMY:
+ spot = mapMarks.alife_presentation_squad_enemy_debug;
+ break;
+ }
+ }
+ /**
+ * Display only minimap marks.
+ * Do not display for offline objects.
+ */
+ } else if (!isSquadMonsterCommunity(squad.faction)) {
+ const relation: Optional = getSquadMembersRelationToActor(squad);
+
+ switch (relation) {
+ case ERelation.FRIEND:
+ spot = mapMarks.alife_presentation_squad_friend;
+ break;
+
+ case ERelation.NEUTRAL:
+ spot = mapMarks.alife_presentation_squad_neutral;
+ break;
+ }
+ }
+
+ if (spot) {
+ const hint: TLabel = squad.getMapDisplayHint();
+ const hasMapSpot: boolean = level.map_has_object_spot(squad.currentMapSpotId, spot) === 1;
+
+ if (spot === squad.currentMapSpotSection && hasMapSpot) {
+ return level.map_change_spot_hint(squad.currentMapSpotId, spot, hint);
+ }
+
+ if (squad.currentMapSpotSection === null || !hasMapSpot) {
+ level.map_add_object_spot(squad.currentMapSpotId, spot, hint);
+ } else {
+ level.map_remove_object_spot(squad.currentMapSpotId, squad.currentMapSpotSection);
+ level.map_add_object_spot(squad.currentMapSpotId, spot, hint);
+ }
+
+ squad.currentMapSpotSection = spot;
+ } else if (squad.currentMapSpotSection) {
+ level.map_remove_object_spot(squad.currentMapSpotId, squad.currentMapSpotSection);
+ squad.currentMapSpotSection = null;
+ }
+ }
+
+ /**
+ * Remove map spot for squad.
+ *
+ * @param squad - target squad server object
+ */
+ public removeSquadMapSpot(squad: Squad): void {
+ if (squad.currentMapSpotId === null || squad.currentMapSpotSection === null) {
+ return;
+ }
+
+ level.map_remove_object_spot(squad.currentMapSpotId, squad.currentMapSpotSection);
+
+ squad.currentMapSpotId = null;
+ squad.currentMapSpotSection = null;
+ }
+
+ /**
+ * todo: Description.
+ */
+ public updateSmartTerrainMapSpot(smartTerrain: SmartTerrain): void {
+ /**
+ * If debug enabled, render map spots.
+ */
+ if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
+ let spot: ERelation = ERelation.NEUTRAL;
+
+ if (
+ smartTerrain.isSimulationAvailableConditionList === null ||
+ pickSectionFromCondList(registry.actor, smartTerrain, smartTerrain.isSimulationAvailableConditionList) === TRUE
+ ) {
+ spot = ERelation.FRIEND;
+ } else {
+ spot = ERelation.ENEMY;
+ }
+
+ const previousSelector: TName = string.format(
+ "alife_presentation_smart_%s_%s",
+ smartTerrain.simulationRole,
+ smartTerrain.smartTerrainDisplayedMapSpot
+ );
+
+ if (smartTerrain.smartTerrainDisplayedMapSpot === spot) {
+ level.map_change_spot_hint(smartTerrain.id, previousSelector, smartTerrain.getMapDisplayHint());
+
+ return;
+ }
+
+ // If previous mark is defined.
+ if (smartTerrain.smartTerrainDisplayedMapSpot !== null) {
+ level.map_remove_object_spot(smartTerrain.id, previousSelector);
+ }
+
+ // If next mark is defined.
+ if (spot !== null) {
+ const nextSelector: TName = string.format("alife_presentation_smart_%s_%s", smartTerrain.simulationRole, spot);
+
+ level.map_add_object_spot(smartTerrain.id, nextSelector, smartTerrain.getMapDisplayHint());
+ }
+
+ smartTerrain.smartTerrainDisplayedMapSpot = spot;
+
+ return;
+ }
+
+ /**
+ * If not enabled rendering, just remove map spot if needed.
+ */
+ if (
+ smartTerrain.smartTerrainDisplayedMapSpot !== null &&
+ level.map_has_object_spot(
+ smartTerrain.id,
+ "alife_presentation_smart_" + smartTerrain.simulationRole + "_" + smartTerrain.smartTerrainDisplayedMapSpot
+ )
+ ) {
+ level.map_remove_object_spot(
+ smartTerrain.id,
+ "alife_presentation_smart_" + smartTerrain.simulationRole + "_" + smartTerrain.smartTerrainDisplayedMapSpot
+ );
+ smartTerrain.smartTerrainDisplayedMapSpot = null;
+ }
+ }
+
/**
* todo: Description.
*/
@@ -192,6 +387,20 @@ export class MapDisplayManager extends AbstractCoreManager {
this.updateSleepZonesDisplay();
}
+ /**
+ * todo: Description.
+ */
+ public removeSmartTerrainMapSpot(smartTerrain: SmartTerrain): void {
+ if (smartTerrain.smartTerrainDisplayedMapSpot === null) {
+ return;
+ }
+
+ level.map_remove_object_spot(
+ smartTerrain.id,
+ "alife_presentation_smart_" + smartTerrain.simulationRole + "_" + smartTerrain.smartTerrainDisplayedMapSpot
+ );
+ }
+
/**
* todo: Description.
*/
@@ -234,11 +443,9 @@ export class MapDisplayManager extends AbstractCoreManager {
const objectId: Optional = getObjectIdByStoryId(scanner.target);
let hint: TLabel = game.translate_string(scanner.hint) + "\\n" + " \\n";
- const actor: ClientObject = registry.actor;
+ const artefactTable: LuaArray = getAnomalyArtefacts(scanner.zone);
- const [hasArtefact, artefactTable] = anomalyHasArtefact(actor, null, scanner.zone, null);
-
- if (hasArtefact) {
+ if (artefactTable.length() > 0) {
hint = hint + game.translate_string(captions.st_jup_b32_has_af);
for (const [k, v] of artefactTable!) {
hint = hint + "\\n" + game.translate_string("st_" + v + "_name");
@@ -260,7 +467,7 @@ export class MapDisplayManager extends AbstractCoreManager {
}
/**
- * todo: Description.
+ * Handle update tick for map display.
*/
public override update(): void {
const now: TTimestamp = time_global();
diff --git a/src/engine/core/managers/world/DropManager.ts b/src/engine/core/managers/world/DropManager.ts
index 476dea526..d56aa86cf 100644
--- a/src/engine/core/managers/world/DropManager.ts
+++ b/src/engine/core/managers/world/DropManager.ts
@@ -171,6 +171,7 @@ export class DropManager extends AbstractCoreManager {
/**
* todo;
+ *
* @param object - target object to create release items.
*/
public createCorpseReleaseItems(object: ClientObject): void {
diff --git a/src/engine/core/managers/world/WeatherManager.ts b/src/engine/core/managers/world/WeatherManager.ts
index 28f9ace14..984a97e83 100644
--- a/src/engine/core/managers/world/WeatherManager.ts
+++ b/src/engine/core/managers/world/WeatherManager.ts
@@ -244,6 +244,7 @@ export class WeatherManager extends AbstractCoreManager {
/**
* Transform current state into string.
+ *
* @returns string containing level states, example: `dynamic_default=clear,cloudy;another=cloudy,rainy`
*/
public getStateAsString(): string {
diff --git a/src/engine/core/objects/binders/creature/ActorBinder.ts b/src/engine/core/objects/binders/creature/ActorBinder.ts
index 441891f4f..7eed2465d 100644
--- a/src/engine/core/objects/binders/creature/ActorBinder.ts
+++ b/src/engine/core/objects/binders/creature/ActorBinder.ts
@@ -5,12 +5,14 @@ import {
closeSaveMarker,
destroyPortableStore,
initializePortableStore,
+ loadPortableStore,
+ openLoadMarker,
openSaveMarker,
+ registerActor,
registry,
+ savePortableStore,
+ unregisterActor,
} from "@/engine/core/database";
-import { registerActor, unregisterActor } from "@/engine/core/database/actor";
-import { loadPortableStore, savePortableStore } from "@/engine/core/database/portable_store";
-import { openLoadMarker } from "@/engine/core/database/save_markers";
import { updateSimulationObjectAvailability } from "@/engine/core/database/simulation";
import { SaveManager } from "@/engine/core/managers/base/SaveManager";
import { EventsManager } from "@/engine/core/managers/events/EventsManager";
@@ -144,16 +146,14 @@ export class ActorBinder extends object_binder {
}
public override save(packet: NetPacket): void {
- logger.info("Save");
-
openSaveMarker(packet, ActorBinder.__name);
super.save(packet);
savePortableStore(this.object, packet);
- SaveManager.getInstance().save(packet);
+ SaveManager.getInstance().clientSave(packet);
- // todo: Move out deimos logic.
+ // todo: Move out deimos logic. Probably store in pstore?
let isDeimosExisting: boolean = false;
for (const [id, zone] of registry.zones) {
@@ -175,8 +175,6 @@ export class ActorBinder extends object_binder {
}
public override load(reader: Reader): void {
- logger.info("Load");
-
this.isFirstUpdatePerformed = false;
openLoadMarker(reader, ActorBinder.__name);
@@ -184,7 +182,7 @@ export class ActorBinder extends object_binder {
super.load(reader);
loadPortableStore(this.object, reader);
- SaveManager.getInstance().load(reader);
+ SaveManager.getInstance().clientLoad(reader);
// todo: Move out deimos logic.
const hasDeimos: boolean = reader.r_bool();
diff --git a/src/engine/core/objects/binders/creature/CrowBinder.ts b/src/engine/core/objects/binders/creature/CrowBinder.ts
index 299e83560..509f2fe92 100644
--- a/src/engine/core/objects/binders/creature/CrowBinder.ts
+++ b/src/engine/core/objects/binders/creature/CrowBinder.ts
@@ -3,14 +3,15 @@ import { alife, callback, LuabindClass, object_binder, time_global } from "xray1
import {
closeLoadMarker,
closeSaveMarker,
+ loadObjectLogic,
+ openLoadMarker,
openSaveMarker,
registerObject,
registry,
resetObject,
+ saveObjectLogic,
unregisterObject,
} from "@/engine/core/database";
-import { loadObjectLogic, saveObjectLogic } from "@/engine/core/database/logic";
-import { openLoadMarker } from "@/engine/core/database/save_markers";
import { LuaLogger } from "@/engine/core/utils/logging";
import { logicsConfig } from "@/engine/lib/configs/LogicsConfig";
import {
diff --git a/src/engine/core/objects/binders/zones/AnomalyZoneBinder.ts b/src/engine/core/objects/binders/zones/AnomalyZoneBinder.ts
index a530ee020..74b4087d3 100644
--- a/src/engine/core/objects/binders/zones/AnomalyZoneBinder.ts
+++ b/src/engine/core/objects/binders/zones/AnomalyZoneBinder.ts
@@ -457,7 +457,7 @@ export class AnomalyZoneBinder extends object_binder {
this.artefactWaysByArtefactId.set(artefactObject.id, randomPathName);
this.artefactPointsByArtefactId.set(artefactObject.id, randomPathPoint);
- this.spawnedArtefactsCount = this.spawnedArtefactsCount + 1;
+ this.spawnedArtefactsCount += 1;
logger.info("Spawned random artefact:", randomArtefact, artefactObject.id);
}
diff --git a/src/engine/core/objects/server/creature/Actor.ts b/src/engine/core/objects/server/creature/Actor.ts
index bea066c30..0cce4a7d0 100644
--- a/src/engine/core/objects/server/creature/Actor.ts
+++ b/src/engine/core/objects/server/creature/Actor.ts
@@ -32,6 +32,7 @@ import {
Optional,
ServerCreatureObject,
TNumberId,
+ TSize,
Vector,
} from "@/engine/lib/types";
@@ -70,15 +71,15 @@ export class Actor extends cse_alife_creature_actor implements ISimulationTarget
super.STATE_Write(packet);
openSaveMarker(packet, Actor.__name);
- SaveManager.getInstance().writeState(packet);
+ SaveManager.getInstance().serverSave(packet);
closeSaveMarker(packet, Actor.__name);
}
- public override STATE_Read(packet: NetPacket, size: number): void {
+ public override STATE_Read(packet: NetPacket, size: TSize): void {
super.STATE_Read(packet, size);
openLoadMarker(packet, Actor.__name);
- SaveManager.getInstance().readState(packet);
+ SaveManager.getInstance().serverLoad(packet);
closeLoadMarker(packet, Actor.__name);
}
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_anim_pri_a22.ts b/src/engine/core/objects/server/smart_cover/smart_covers_anim_pri_a22.ts
index 41cd6a164..ea5aa4413 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_anim_pri_a22.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_anim_pri_a22.ts
@@ -4,6 +4,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimPriA22Loophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_anim_pri_a22";
import { createEmptyVector, createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimPriA22(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_pri_a15.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_pri_a15.ts
index 98fd10769..ab7d0c299 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_pri_a15.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_pri_a15.ts
@@ -4,6 +4,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointPriA15Loophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_pri_a15";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointPriA15(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_high.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_high.ts
index 2a40dc492..3d24dc830 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_high.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_high.ts
@@ -4,6 +4,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointSitHighLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_high";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointSitHigh(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_low.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_low.ts
index 5e6dd6cb3..8cd1550b8 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_low.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_low.ts
@@ -4,6 +4,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointSitLowLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_low";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointSitLow(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_normal.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_normal.ts
index 49c5694fb..0c3428c96 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_normal.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_sit_normal.ts
@@ -5,6 +5,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointSitNormalLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_normal";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointSitNormal(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_table.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_table.ts
index ff43a07b9..44cd2b656 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_table.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_table.ts
@@ -5,6 +5,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointStayTableLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_table";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointStayTable(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_wall.ts b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_wall.ts
index 4088c5a56..4f5db4ceb 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_wall.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_animpoint_stay_wall.ts
@@ -4,6 +4,9 @@ import { ISmartCoverDescriptor } from "@/engine/core/objects/server/smart_cover/
import { getAnimpointStayWallLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_wall";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
export function getSmartCoverAnimpointStayWall(): ISmartCoverDescriptor {
return {
need_weapon: false,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_combat.ts b/src/engine/core/objects/server/smart_cover/smart_covers_combat.ts
index 64c754363..99e59889b 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_combat.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_combat.ts
@@ -13,6 +13,9 @@ import { getStandLeftLoophole } from "@/engine/core/objects/server/smart_cover/s
import { getStandRightLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_right";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ * todo;
+ */
function getSmartCoverCombat(): ISmartCoverDescriptor {
return {
need_weapon: true,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_combat_front.ts b/src/engine/core/objects/server/smart_cover/smart_covers_combat_front.ts
index 6dfe341b5..48a60e3b7 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_combat_front.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_combat_front.ts
@@ -8,6 +8,9 @@ import { getStandFrontLeftLoophole } from "@/engine/core/objects/server/smart_co
import { getStandFrontRightLoophole } from "@/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_right";
import { createVector } from "@/engine/core/utils/vector";
+/**
+ *
+ */
export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
return {
need_weapon: true,
@@ -500,7 +503,7 @@ export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
vertex1: "",
weight: 1.1,
actions: [
- /** ### {
+ /* ### {
precondition_functor: "xr_conditions.always",
precondition_params: "",
@@ -531,7 +534,8 @@ export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
vertex1: "",
weight: 1.1,
actions: [
- /** ### {
+ /**
+ ### {
precondition_functor: "xr_conditions.always",
precondition_params: "",
actions = {
@@ -541,7 +545,8 @@ export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
body_state: move.crouch, movement_type: move.run,
},
},
- },*/
+ },
+ */
{
precondition_functor: "xr_conditions.always",
precondition_params: "",
@@ -561,7 +566,8 @@ export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
vertex1: "",
weight: 1.1,
actions: [
- /** ### {
+ /*
+ ### {
precondition_functor: "xr_conditions.always",
precondition_params: "",
actions = {
@@ -571,7 +577,8 @@ export function getSmartCoverCombatFront(): ISmartCoverDescriptor {
body_state: move.crouch, movement_type: move.run,
},
},
- },*/
+ },
+ */
{
precondition_functor: "xr_conditions.always",
precondition_params: "",
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_combat_prone.ts b/src/engine/core/objects/server/smart_cover/smart_covers_combat_prone.ts
index 5823e31eb..cc2aeaafe 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_combat_prone.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_combat_prone.ts
@@ -5,6 +5,9 @@ import { createVector } from "@/engine/core/utils/vector";
import { getProneLoophole } from "./smart_covers_loophole_prone";
+/**
+ * todo;
+ */
export function getSmartCoverCombatProne(): ISmartCoverDescriptor {
return {
loopholes: [getProneLoophole("prone", createVector(-1, 0, 0))] as any,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_anim_pri_a22.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_anim_pri_a22.ts
index 8d3fa1b69..ad12472fc 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_anim_pri_a22.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_anim_pri_a22.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimPriA22Loophole(
id: TStringId,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_pri_a15.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_pri_a15.ts
index 3c87b2377..60dae4535 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_pri_a15.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_pri_a15.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointPriA15Loophole(
id: string,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_high.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_high.ts
index 87ba63333..16ba396b4 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_high.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_high.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointSitHighLoophole(
id: string,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_low.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_low.ts
index e17fa8b4f..c874bddb1 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_low.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_low.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointSitLowLoophole(
id: TStringId,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_normal.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_normal.ts
index 5d180b1f0..9f318eb1a 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_normal.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_sit_normal.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointSitNormalLoophole(
id: TStringId,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_table.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_table.ts
index 7480fbc2c..3152df35f 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_table.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_table.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointStayTableLoophole(
id: TStringId,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_wall.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_wall.ts
index 5bfc57021..e25391023 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_wall.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_animpoint_stay_wall.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointStayWallLoophole(
id: TStringId,
position: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_back.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_back.ts
index a6ff48284..604439d3f 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_back.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_back.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createEmptyVector, createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchBackLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front.ts
index 7767b62ab..cb2ce17c0 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchFrontLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_left.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_left.ts
index f4588d86e..f263306a2 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_left.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_left.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchFrontLeftLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_right.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_right.ts
index aca09d0f1..11859e54f 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_right.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_front_right.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchFrontRightLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_left.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_left.ts
index 37dda8a85..8fe800b6b 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_left.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_left.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createEmptyVector, createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchLeftLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_right.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_right.ts
index 46ec2b62c..c19a31db9 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_right.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_crouch_right.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createEmptyVector, createVector } from "@/engine/core/utils/vector";
import { TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getCrouchRightLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_prone.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_prone.ts
index e57dee14e..d6f946c19 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_prone.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_prone.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getProneLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_back.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_back.ts
index 60d41952c..41f3f2146 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_back.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_back.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getStandBackLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_left.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_left.ts
index aa902c3d1..a46fca60e 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_left.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_left.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getStandFrontLeftLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_right.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_right.ts
index 110c9dbfc..4a1e86a61 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_right.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_front_right.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getStandFrontRightLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_left.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_left.ts
index dbbe968bf..6f658702c 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_left.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_left.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getStandLeftLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_right.ts b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_right.ts
index f654c8e31..2c58004c8 100644
--- a/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_right.ts
+++ b/src/engine/core/objects/server/smart_cover/smart_covers_loophole_stand_right.ts
@@ -2,6 +2,9 @@ import { ISmartCoverLoopholeDescriptor } from "@/engine/core/objects/server/smar
import { createVector } from "@/engine/core/utils/vector";
import { Optional, TStringId, Vector } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getStandRightLoophole(
id: TStringId,
fovDirection: Vector,
diff --git a/src/engine/core/objects/server/smart_terrain/SmartTerrain.ts b/src/engine/core/objects/server/smart_terrain/SmartTerrain.ts
index 54770b0e8..b15890fbf 100644
--- a/src/engine/core/objects/server/smart_terrain/SmartTerrain.ts
+++ b/src/engine/core/objects/server/smart_terrain/SmartTerrain.ts
@@ -32,6 +32,7 @@ import {
updateSimulationObjectAvailability,
} from "@/engine/core/database/simulation";
import { SimulationBoardManager } from "@/engine/core/managers/interaction/SimulationBoardManager";
+import { MapDisplayManager } from "@/engine/core/managers/interface";
import {
areOnlyMonstersOnJobs,
jobIterator,
@@ -115,17 +116,17 @@ import {
const logger: LuaLogger = new LuaLogger($filename);
-export const path_fields: LuaArray = $fromArray(["path_walk", "path_main", "path_home", "center_point"]);
+export const PATH_FIELDS: LuaArray = $fromArray(["path_walk", "path_main", "path_home", "center_point"]);
/**
* todo;
*/
-export const valid_territory: LuaTable = {
+export const VALID_SMART_TERRAINS_SIMULATION_ROLES: LuaTable = $fromObject({
default: true,
base: true,
resource: true,
territory: true,
-} as any;
+});
/**
* todo;
@@ -201,7 +202,8 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
public jobDeadTimeById: LuaTable = new LuaTable(); // job id -> time
public simulationProperties!: AnyObject;
- public simulationBoardManager!: SimulationBoardManager;
+ public simulationBoardManager: SimulationBoardManager = SimulationBoardManager.getInstance();
+ public mapDisplayManager: MapDisplayManager = MapDisplayManager.getInstance();
public respawnConfiguration!: LuaTable; num: TConditionList }>;
public alreadySpawned!: LuaTable;
@@ -209,7 +211,6 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
public override on_before_register(): void {
super.on_before_register();
- this.simulationBoardManager = SimulationBoardManager.getInstance();
this.simulationBoardManager.registerSmartTerrain(this);
this.level = alife().level_name(game_graph().vertex(this.m_game_vertex_id).level_id());
}
@@ -221,7 +222,7 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
registerSimulationObject(this);
if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
- this.updateMapDisplay();
+ this.mapDisplayManager.updateSmartTerrainMapSpot(this);
}
this.smartTerrainAlifeTask = new CALifeSmartTerrainTask(this.m_game_vertex_id, this.m_level_vertex_id);
@@ -492,8 +493,8 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
public override update(): void {
super.update();
- if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED || this.smartTerrainDisplayedMapSpot !== null) {
- this.updateMapDisplay();
+ if (this.smartTerrainDisplayedMapSpot !== null || gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
+ this.mapDisplayManager.updateSmartTerrainMapSpot(this);
}
const now: TTimestamp = time_global();
@@ -586,7 +587,7 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
ESimulationTerrainRole.DEFAULT
) as ESimulationTerrainRole;
- if (valid_territory.get(this.simulationRole) === null) {
+ if (VALID_SMART_TERRAINS_SIMULATION_ROLES.get(this.simulationRole) === null) {
abort("Wrong sim_type value [%s] in smart [%s]", this.simulationRole, this.name());
}
@@ -792,7 +793,7 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
if (job.job_type === "path_job") {
let path_field: string = "";
- for (const [i, vv] of path_fields) {
+ for (const [i, vv] of PATH_FIELDS) {
if (ltx.line_exist(active_section, vv)) {
path_field = vv;
break;
@@ -1130,90 +1131,6 @@ export class SmartTerrain extends cse_alife_smart_zone implements ISimulationTar
}
}
- /**
- * todo: Description.
- */
- public updateMapDisplay(): void {
- /**
- * If debug enabled, render map spots.
- */
- if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
- let spot: ERelation = ERelation.NEUTRAL;
-
- if (
- this.isSimulationAvailableConditionList === null ||
- pickSectionFromCondList(registry.actor, this, this.isSimulationAvailableConditionList) === TRUE
- ) {
- spot = ERelation.FRIEND;
- } else {
- spot = ERelation.ENEMY;
- }
-
- const previousSelector: TName = string.format(
- "alife_presentation_smart_%s_%s",
- tostring(this.simulationRole),
- tostring(this.smartTerrainDisplayedMapSpot)
- );
-
- if (this.smartTerrainDisplayedMapSpot === spot) {
- level.map_change_spot_hint(this.id, previousSelector, this.getMapDisplayHint());
-
- return;
- }
-
- // If previous mark is defined.
- if (this.smartTerrainDisplayedMapSpot !== null) {
- level.map_remove_object_spot(this.id, previousSelector);
- }
-
- // If next mark is defined.
- if (spot !== null) {
- const nextSelector: TName = string.format(
- "alife_presentation_smart_%s_%s",
- tostring(this.simulationRole),
- tostring(spot)
- );
-
- level.map_add_object_spot(this.id, nextSelector, this.getMapDisplayHint());
- }
-
- this.smartTerrainDisplayedMapSpot = spot;
-
- return;
- }
-
- /**
- * If not enabled rendering, just remove map spot if needed.
- */
- if (
- this.smartTerrainDisplayedMapSpot !== null &&
- level.map_has_object_spot(
- this.id,
- "alife_presentation_smart_" + this.simulationRole + "_" + this.smartTerrainDisplayedMapSpot
- )
- ) {
- level.map_remove_object_spot(
- this.id,
- "alife_presentation_smart_" + this.simulationRole + "_" + this.smartTerrainDisplayedMapSpot
- );
- this.smartTerrainDisplayedMapSpot = null;
- }
- }
-
- /**
- * todo: Description.
- */
- public hide(): void {
- if (this.smartTerrainDisplayedMapSpot === null) {
- return;
- }
-
- level.map_remove_object_spot(
- this.id,
- "alife_presentation_smart_" + this.simulationRole + "_" + this.smartTerrainDisplayedMapSpot
- );
- }
-
/**
* Trigger smart terrain alarm.
*/
diff --git a/src/engine/core/objects/server/squad/Squad.ts b/src/engine/core/objects/server/squad/Squad.ts
index c1936029f..507f70947 100644
--- a/src/engine/core/objects/server/squad/Squad.ts
+++ b/src/engine/core/objects/server/squad/Squad.ts
@@ -29,6 +29,7 @@ import {
} from "@/engine/core/database/simulation";
import { unregisterStoryLinkByObjectId } from "@/engine/core/database/story_objects";
import { SimulationBoardManager } from "@/engine/core/managers/interaction/SimulationBoardManager";
+import { MapDisplayManager } from "@/engine/core/managers/interface/MapDisplayManager";
import type { SmartTerrain } from "@/engine/core/objects/server/smart_terrain/SmartTerrain";
import { ESmartTerrainStatus } from "@/engine/core/objects/server/smart_terrain/types";
import { SquadReachTargetAction, SquadStayOnTargetAction } from "@/engine/core/objects/server/squad/action";
@@ -53,25 +54,17 @@ import {
TConditionList,
} from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { areObjectsOnSameLevel, hasAlifeInfo, isSquadMonsterCommunity } from "@/engine/core/utils/object";
-import {
- areCommunitiesEnemies,
- ERelation,
- getSquadMembersRelationToActor,
- getSquadMembersRelationToActorSafe,
- setObjectSympathy,
-} from "@/engine/core/utils/relation";
+import { areObjectsOnSameLevel, hasAlifeInfo } from "@/engine/core/utils/object";
+import { areCommunitiesEnemies, ERelation, setObjectSympathy } from "@/engine/core/utils/relation";
import { isEmpty } from "@/engine/core/utils/table";
import { gameConfig } from "@/engine/lib/configs/GameConfig";
import { squadCommunityByBehaviour } from "@/engine/lib/constants/behaviours";
import { communities, TCommunity } from "@/engine/lib/constants/communities";
import { infoPortions } from "@/engine/lib/constants/info_portions";
-import { mapMarks } from "@/engine/lib/constants/map_marks";
import { MAX_U16 } from "@/engine/lib/constants/memory";
import { SMART_TERRAIN_SECTION } from "@/engine/lib/constants/sections";
import { FALSE, NIL, TRUE } from "@/engine/lib/constants/words";
import {
- AlifeSimulator,
ALifeSmartTerrainTask,
AnyObject,
ClientObject,
@@ -93,7 +86,7 @@ import { TSection } from "@/engine/lib/types/scheme";
const logger: LuaLogger = new LuaLogger($filename);
/**
- * todo;
+ * Server object implementation for squad groups.
*/
@LuabindClass()
export class Squad extends cse_alife_online_offline_group implements ISimulationTarget {
@@ -110,6 +103,7 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
public assignedSmartTerrainId: Optional = null;
public enteredSmartTerrainId: Optional = null;
+ public mapDisplayManager: MapDisplayManager = MapDisplayManager.getInstance();
public simulationBoardManager: SimulationBoardManager = SimulationBoardManager.getInstance();
public simulationProperties!: AnyObject;
@@ -150,7 +144,7 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
public override update(): void {
super.update();
- this.refreshMapDisplay();
+ this.mapDisplayManager.updateSquadMapSpot(this);
updateSimulationObjectAvailability(this);
@@ -545,7 +539,7 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
}
}
- this.hideMapDisplay();
+ this.mapDisplayManager.removeSquadMapSpot(this);
}
/**
@@ -574,7 +568,7 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
return;
}
- this.refreshMapDisplay();
+ this.mapDisplayManager.updateSquadMapSpot(this);
}
/**
@@ -803,7 +797,7 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
}
this.assignedSmartTerrainId = spawnSmartTerrain.id;
- this.refreshMapDisplay();
+ this.mapDisplayManager.updateSquadMapSpot(this);
}
/**
@@ -874,124 +868,6 @@ export class Squad extends cse_alife_online_offline_group implements ISimulation
return squadCommunity;
}
- /**
- * todo: Description.
- */
- public refreshMapDisplay(): void {
- if (this.commander_id() === null) {
- return this.hideMapDisplay();
- }
-
- this.updateMapDisplay();
- }
-
- /**
- * todo: Description.
- */
- public hideMapDisplay(): void {
- if (this.currentMapSpotId === null || this.currentMapSpotSection === null) {
- return;
- }
-
- level.map_remove_object_spot(this.currentMapSpotId, this.currentMapSpotSection);
-
- this.currentMapSpotId = null;
- this.currentMapSpotSection = null;
- }
-
- /**
- * todo: Description.
- */
- public updateMapDisplay(): void {
- if (this.isMapDisplayHidden) {
- return this.hideMapDisplay();
- }
-
- const squadCommanderId: TNumberId = this.commander_id();
-
- if (this.currentMapSpotId !== squadCommanderId) {
- this.hideMapDisplay();
- this.currentMapSpotId = squadCommanderId;
- this.updateMapDisplay();
-
- return;
- }
-
- if (
- level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_trader_location) !== 0 ||
- level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_mechanic_location) !== 0 ||
- level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_scout_location) !== 0 ||
- level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_quest_npc_location) !== 0 ||
- level.map_has_object_spot(squadCommanderId, mapMarks.ui_pda2_medic_location) !== 0
- ) {
- this.isMapDisplayHidden = true;
-
- return;
- }
-
- let spot: Optional = null;
-
- /**
- * In case of debug use map display like in clear sky.
- */
- if (gameConfig.DEBUG.IS_SIMULATION_DEBUG_ENABLED) {
- if (isSquadMonsterCommunity(this.faction)) {
- spot = mapMarks.alife_presentation_squad_monster_debug;
- } else {
- const relation: ERelation = getSquadMembersRelationToActorSafe(this);
-
- switch (relation) {
- case ERelation.FRIEND:
- spot = mapMarks.alife_presentation_squad_friend_debug;
- break;
- case ERelation.NEUTRAL:
- spot = mapMarks.alife_presentation_squad_neutral_debug;
- break;
- case ERelation.ENEMY:
- spot = mapMarks.alife_presentation_squad_enemy_debug;
- break;
- }
- }
- /**
- * Display only minimap marks.
- * Do not display for offline objects.
- */
- } else if (!isSquadMonsterCommunity(this.faction)) {
- const relation: Optional = getSquadMembersRelationToActor(this);
-
- switch (relation) {
- case ERelation.FRIEND:
- spot = mapMarks.alife_presentation_squad_friend;
- break;
-
- case ERelation.NEUTRAL:
- spot = mapMarks.alife_presentation_squad_neutral;
- break;
- }
- }
-
- if (spot) {
- const hint: TLabel = this.getMapDisplayHint();
- const hasMapSpot: boolean = level.map_has_object_spot(this.currentMapSpotId, spot) === 1;
-
- if (spot === this.currentMapSpotSection && hasMapSpot) {
- return level.map_change_spot_hint(this.currentMapSpotId, spot, hint);
- }
-
- if (this.currentMapSpotSection === null || !hasMapSpot) {
- level.map_add_object_spot(this.currentMapSpotId, spot, hint);
- } else {
- level.map_remove_object_spot(this.currentMapSpotId, this.currentMapSpotSection);
- level.map_add_object_spot(this.currentMapSpotId, spot, hint);
- }
-
- this.currentMapSpotSection = spot;
- } else if (this.currentMapSpotSection) {
- level.map_remove_object_spot(this.currentMapSpotId, this.currentMapSpotSection);
- this.currentMapSpotSection = null;
- }
- }
-
/**
* Get map display hint for debugging and display in game UI map.
*/
diff --git a/src/engine/core/objects/state/add_state_manager.ts b/src/engine/core/objects/state/add_state_manager.ts
index 01541740b..c3acfd056 100644
--- a/src/engine/core/objects/state/add_state_manager.ts
+++ b/src/engine/core/objects/state/add_state_manager.ts
@@ -27,6 +27,7 @@ const logger: LuaLogger = new LuaLogger($filename);
/**
* Add state manager instance to Stalker object.
+ *
* @param object
*/
export function addStateManager(object: ClientObject): StalkerStateManager {
diff --git a/src/engine/core/objects/state_lib/state_manager_scenario.ts b/src/engine/core/objects/state_lib/state_manager_scenario.ts
index 5f4ee236d..f9d7aedbd 100644
--- a/src/engine/core/objects/state_lib/state_manager_scenario.ts
+++ b/src/engine/core/objects/state_lib/state_manager_scenario.ts
@@ -798,6 +798,9 @@ export function getStateLibScenarios(): LuaTable {
} as any;
}
+/**
+ * todo;
+ */
export function getAnimationListScenario(): LuaTable {
return {
zat_b14_give_artefact_idle: {
diff --git a/src/engine/core/objects/state_lib/state_mgr_animation_list_animpoint.ts b/src/engine/core/objects/state_lib/state_mgr_animation_list_animpoint.ts
index afbb3ddda..6b04e210b 100644
--- a/src/engine/core/objects/state_lib/state_mgr_animation_list_animpoint.ts
+++ b/src/engine/core/objects/state_lib/state_mgr_animation_list_animpoint.ts
@@ -1,6 +1,9 @@
import { IAnimationDescriptor } from "@/engine/core/objects/state/types";
import { ClientObject } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function getAnimpointAnimationList(): LuaTable {
return {
animpoint_stay_wall: {
diff --git a/src/engine/core/objects/state_lib/state_mgr_animstate_list_animpoint.ts b/src/engine/core/objects/state_lib/state_mgr_animstate_list_animpoint.ts
index c42962644..d85345011 100644
--- a/src/engine/core/objects/state_lib/state_mgr_animstate_list_animpoint.ts
+++ b/src/engine/core/objects/state_lib/state_mgr_animstate_list_animpoint.ts
@@ -2,6 +2,9 @@ import { IAnimationStateDescriptor } from "@/engine/core/objects/state/types";
import { getExtern } from "@/engine/core/utils/binding";
import { AnyArgs, AnyCallablesModule } from "@/engine/lib/types";
+/**
+ * todo;
+ */
export function addAnimstateAnimationList(): LuaTable {
return {
animpoint_stay_wall: {
diff --git a/src/engine/core/objects/state_lib/state_mgr_pri_a15.ts b/src/engine/core/objects/state_lib/state_mgr_pri_a15.ts
index bc8c2ee38..0387b52eb 100644
--- a/src/engine/core/objects/state_lib/state_mgr_pri_a15.ts
+++ b/src/engine/core/objects/state_lib/state_mgr_pri_a15.ts
@@ -23,6 +23,9 @@ const WEAP_TABLE_UNSTRAPPED: LuaArray = [
"pri_a15_wpn_ak74_unstrapped",
] as any;
+/**
+ * todo;
+ */
function unstrapWeapon(object: ClientObject): void {
let item: Optional = null;
let index: TIndex = 0;
@@ -42,6 +45,9 @@ function unstrapWeapon(object: ClientObject): void {
item.attachable_item_load_attach(WEAP_TABLE_UNSTRAPPED.get(index as number));
}
+/**
+ * todo;
+ */
function strapWeapon(object: ClientObject): void {
let item: Optional = null;
let index: TIndex = 0;
@@ -61,18 +67,30 @@ function strapWeapon(object: ClientObject): void {
item.attachable_item_load_attach(WEAP_TABLE.get(index));
}
+/**
+ * todo;
+ */
function breakFence(): void {
registry.doors.get(storyNames.pri_a15_door).forwardAnimation();
}
+/**
+ * todo;
+ */
function lightsOff(): void {
registry.actor.give_info_portion(infoPortions.pri_a15_lights_off);
}
+/**
+ * todo;
+ */
function lightsOn(): void {
registry.actor.disable_info_portion(infoPortions.pri_a15_lights_off);
}
+/**
+ * todo;
+ */
function endScene(): void {
registry.actor.give_info_portion(infoPortions.pri_a15_cutscene_end);
}
@@ -616,6 +634,9 @@ const cutscene: Record<
},
};
+/**
+ *
+ */
function check_availability(precondition: LuaArray, existing_npc: string): boolean {
const check_names = parseStringsList(existing_npc);
@@ -703,6 +724,9 @@ function get_sequence_for_npc(objectName: TName, existing_npc: string): TNpcSequ
return result;
}
+/**
+ *
+ */
export function addStateLibPriA15(): LuaTable {
return {
pri_a15_idle_none: {
@@ -1850,6 +1874,9 @@ export function addStateLibPriA15(): LuaTable {
} as any;
}
+/**
+ * todo;
+ */
export function addAnimationListPriA15(): LuaTable> {
return {
pri_a15_idle_none: {
diff --git a/src/engine/core/schemes/combat_idle/evaluators/EvaluatorPostCombatIdleEnemy.ts b/src/engine/core/schemes/combat_idle/evaluators/EvaluatorPostCombatIdleEnemy.ts
index f3532e201..a17685d4d 100644
--- a/src/engine/core/schemes/combat_idle/evaluators/EvaluatorPostCombatIdleEnemy.ts
+++ b/src/engine/core/schemes/combat_idle/evaluators/EvaluatorPostCombatIdleEnemy.ts
@@ -4,7 +4,7 @@ import { registry } from "@/engine/core/database";
import { ISchemePostCombatIdleState } from "@/engine/core/schemes/combat_idle/ISchemePostCombatIdleState";
import { ISchemeCombatIgnoreState } from "@/engine/core/schemes/combat_ignore";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { isObjectEnemy } from "@/engine/core/utils/object";
+import { canObjectSelectAsEnemy } from "@/engine/core/utils/object";
import { logicsConfig } from "@/engine/lib/configs/LogicsConfig";
import { ClientObject, EScheme, Optional, TDistance, TTimestamp } from "@/engine/lib/types";
@@ -31,7 +31,7 @@ export class EvaluatorPostCombatIdleEnemy extends property_evaluator {
if (
bestEnemy !== null &&
- !isObjectEnemy(
+ !canObjectSelectAsEnemy(
this.object,
bestEnemy,
registry.objects.get(this.object.id())[EScheme.COMBAT_IGNORE] as ISchemeCombatIgnoreState
diff --git a/src/engine/core/schemes/combat_ignore/CombatProcessEnemyManager.ts b/src/engine/core/schemes/combat_ignore/CombatProcessEnemyManager.ts
index 7c2f1c871..cc4f98a7f 100644
--- a/src/engine/core/schemes/combat_ignore/CombatProcessEnemyManager.ts
+++ b/src/engine/core/schemes/combat_ignore/CombatProcessEnemyManager.ts
@@ -5,7 +5,7 @@ import { SmartTerrain } from "@/engine/core/objects/server/smart_terrain/SmartTe
import { AbstractSchemeManager } from "@/engine/core/schemes";
import { ISchemeCombatIgnoreState } from "@/engine/core/schemes/combat_ignore/index";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { isObjectEnemy } from "@/engine/core/utils/object";
+import { canObjectSelectAsEnemy } from "@/engine/core/utils/object";
import { logicsConfig } from "@/engine/lib/configs/LogicsConfig";
import { ACTOR_ID } from "@/engine/lib/constants/ids";
import { MAX_U16 } from "@/engine/lib/constants/memory";
@@ -25,7 +25,7 @@ export class CombatProcessEnemyManager extends AbstractSchemeManager = alife().object(object.id());
diff --git a/src/engine/core/schemes/heli_move/HeliCombat.ts b/src/engine/core/schemes/heli_move/HeliCombat.ts
index 528a4aa29..c4d79a1b8 100644
--- a/src/engine/core/schemes/heli_move/HeliCombat.ts
+++ b/src/engine/core/schemes/heli_move/HeliCombat.ts
@@ -769,6 +769,9 @@ export class HeliCombat {
}
}
+/**
+ * todo;
+ */
export function crossRayCircle(p: Vector, v: Vector, o: Vector, r: number): Vector {
const po: Vector = copyVector(o).sub(p);
const vperp: Vector = createVector(-v.z, 0, v.x);
diff --git a/src/engine/core/schemes/heli_move/HeliFire.ts b/src/engine/core/schemes/heli_move/HeliFire.ts
index 9424d4288..e2bbfd18e 100644
--- a/src/engine/core/schemes/heli_move/HeliFire.ts
+++ b/src/engine/core/schemes/heli_move/HeliFire.ts
@@ -241,6 +241,9 @@ export class HeliFire {
}
}
+/**
+ * todo;
+ */
export function getHeliFirer(object: ClientObject): HeliFire {
if (heliFirer.get(object.id()) === null) {
heliFirer.set(object.id(), new HeliFire(object));
diff --git a/src/engine/core/schemes/heli_move/HeliFly.ts b/src/engine/core/schemes/heli_move/HeliFly.ts
index 86b1de329..46c04ddfb 100644
--- a/src/engine/core/schemes/heli_move/HeliFly.ts
+++ b/src/engine/core/schemes/heli_move/HeliFly.ts
@@ -190,7 +190,9 @@ export class HeliFly {
this.pointByLook = lPoint;
}
}
-
+/**
+ * todo;
+ */
export function getHeliFlyer(object: ClientObject): HeliFly {
if (heliFlyer.get(object.id()) === null) {
heliFlyer.set(object.id(), new HeliFly(object));
diff --git a/src/engine/core/schemes/heli_move/HeliLook.ts b/src/engine/core/schemes/heli_move/HeliLook.ts
index cebf54937..03020fc37 100644
--- a/src/engine/core/schemes/heli_move/HeliLook.ts
+++ b/src/engine/core/schemes/heli_move/HeliLook.ts
@@ -55,6 +55,9 @@ export class HeliLook {
}
}
+/**
+ * todo;
+ */
export function getHeliLooker(object: ClientObject): HeliLook {
if (heliLooker.get(object.id()) === null) {
heliLooker.set(object.id(), new HeliLook(object));
diff --git a/src/engine/core/schemes/remark/actions/ActionRemarkActivity.ts b/src/engine/core/schemes/remark/actions/ActionRemarkActivity.ts
index bd6e8313b..aebb01f33 100644
--- a/src/engine/core/schemes/remark/actions/ActionRemarkActivity.ts
+++ b/src/engine/core/schemes/remark/actions/ActionRemarkActivity.ts
@@ -189,6 +189,10 @@ export function initTarget(
targetString: string
): LuaMultiReturn<[Optional, Optional, Optional]> {
// todo: Simplify.
+
+ /**
+ * todo;
+ */
function parseTarget(targetStr: string): LuaMultiReturn<[Optional, Optional]> {
const [pos] = string.find(targetStr, ",");
@@ -200,6 +204,10 @@ export function initTarget(
}
// todo: Simplify.
+
+ /**
+ * todo;
+ */
function parseType(targetStr: string): LuaMultiReturn<[string, string]> {
const [pos] = string.find(targetStr, "|");
diff --git a/src/engine/core/ui/game/FreeplayDialog.ts b/src/engine/core/ui/game/FreeplayDialog.ts
index 6a5cabc05..034e899a7 100644
--- a/src/engine/core/ui/game/FreeplayDialog.ts
+++ b/src/engine/core/ui/game/FreeplayDialog.ts
@@ -47,6 +47,9 @@ export class FreeplayDialog extends CUIScriptWnd {
let freeplayControl: Optional = null;
+/**
+ * todo;
+ */
export function showFreeplayDialog(selector: string, text: string): void {
if (freeplayControl === null) {
freeplayControl = new FreeplayDialog();
diff --git a/src/engine/core/ui/menu/options/OptionsVideoAdvanced.ts b/src/engine/core/ui/menu/options/OptionsVideoAdvanced.ts
index fe8541604..6a200b84f 100644
--- a/src/engine/core/ui/menu/options/OptionsVideoAdvanced.ts
+++ b/src/engine/core/ui/menu/options/OptionsVideoAdvanced.ts
@@ -86,8 +86,7 @@ export class OptionsVideoAdvanced extends CUIWindow {
owner.preconditions.set(particlesDistanceTrackBar, only2aAndMoreMode);
- /**
- *
+ /*
* _st = xml:InitStatic("video_adv:templ_item", nil)
* xml:InitStatic("video_adv:cap_r2_smap_size", _st)
* ctl = xml:InitComboBox("video_adv:list_r2_smap_size", _st)
@@ -200,7 +199,7 @@ export class OptionsVideoAdvanced extends CUIWindow {
owner.preconditions.set(wetSurfacesCheck, only3andMoreMode);
- /**
+ /*
*
* _st = xml:InitStatic("video_adv:templ_item", nil)
* xml:InitStatic("video_adv:cap_r3_dynamic_wet_surfaces_opt", _st)
@@ -224,14 +223,14 @@ export class OptionsVideoAdvanced extends CUIWindow {
owner.preconditions.set(volumetricSmokeCheck, only3andMoreMode);
- /**
+ /*
* _st = xml:InitStatic("video_adv:templ_item", nil)
* xml:InitStatic("video_adv:cap_r3_msaa_opt", _st)
* ctl = xml:InitCheck("video_adv:check_r3_msaa_opt", _st)
* table.insert(handler.m_preconditions, {func=mode_ge_3, control=_st})
*/
- /**
+ /*
* -- r4_enable_tessellation only r4
* _st = xml:InitStatic("video_adv:templ_item", nil)
* xml:InitStatic("video_adv:cap_r4_tessellation", _st)
@@ -250,7 +249,7 @@ export class OptionsVideoAdvanced extends CUIWindow {
xml.InitStatic("video_adv:cap_60hz", only60HZSetting);
xml.InitCheck("video_adv:check_60hz", only60HZSetting);
- /**
+ /*
* _st = xml:InitStatic("video_adv:templ_item", nil)
* xml:InitStatic("video_adv:cap_always_active", _st)
* xml:InitCheck("video_adv:check_always_active", _st)
@@ -261,30 +260,48 @@ export class OptionsVideoAdvanced extends CUIWindow {
}
}
+/**
+ * todo;
+ */
function only1mode(control: CUIWindow, id: EGameRenderer): void {
control.Enable(id === EGameRenderer.R1);
}
// -- >=R2a
+/**
+ * todo;
+ */
function only2aAndMoreMode(control: CUIWindow, id: EGameRenderer): void {
control.Enable(id >= EGameRenderer.R2A);
}
// -- >=R2
+/**
+ * todo;
+ */
function only2andMoreMode(control: CUIWindow, id: EGameRenderer): void {
control.Enable(id >= EGameRenderer.R2);
}
// -- >=R2.5
+/**
+ * todo;
+ */
function only25andMoreMode(control: CUIWindow, id: EGameRenderer): void {
control.Enable(id >= EGameRenderer.R25);
}
// -- >=R3
+/**
+ * todo;
+ */
function only3andMoreMode(control: CUIWindow, id: EGameRenderer): void {
control.Enable(id >= EGameRenderer.R3);
}
+/**
+ * todo;
+ */
function only3andMoreModeVisible(control: CUIWindow, id: EGameRenderer): void {
const isEnabled: boolean = id >= EGameRenderer.R3;
@@ -292,6 +309,9 @@ function only3andMoreModeVisible(control: CUIWindow, id: EGameRenderer): void {
control.Show(isEnabled);
}
+/**
+ * todo;
+ */
function only3andMoreModeInvisible(control: CUIWindow, id: EGameRenderer): void {
const isEnabled: boolean = id < EGameRenderer.R3;
@@ -299,10 +319,16 @@ function only3andMoreModeInvisible(control: CUIWindow, id: EGameRenderer): void
control.Show(isEnabled);
}
+/**
+ * todo;
+ */
function only4(control: CUIWindow, id: EGameRenderer) {
return id === EGameRenderer.R4;
}
+/**
+ * todo;
+ */
function only4andMore(control: CUIWindow, id: EGameRenderer) {
return id >= EGameRenderer.R4;
}
diff --git a/src/engine/core/utils/game/game_console.test.ts b/src/engine/core/utils/game/game_console.test.ts
index e81db0dc5..7f2564971 100644
--- a/src/engine/core/utils/game/game_console.test.ts
+++ b/src/engine/core/utils/game/game_console.test.ts
@@ -26,9 +26,12 @@ describe("'console' utils", () => {
});
it("'getConsoleFloatCommand' should correctly generate commands", () => {
- gameConsole.get_float = jest.fn((cmd: string) => (cmd === "snd_volume_eff" ? 50.4 : -1));
+ gameConsole.get_float = jest.fn((cmd: string) => (cmd.startsWith("snd_volume_eff") ? 50.4 : -1));
expect(getConsoleFloatCommand(consoleCommands.snd_volume_eff)).toBe(50.4);
expect(gameConsole.get_float).toHaveBeenCalledWith("snd_volume_eff");
+
+ expect(getConsoleFloatCommand(consoleCommands.snd_volume_eff, 1, 2)).toBe(50.4);
+ expect(gameConsole.get_float).toHaveBeenNthCalledWith(2, "snd_volume_eff 1 2");
});
});
diff --git a/src/engine/core/utils/game/game_save.test.ts b/src/engine/core/utils/game/game_save.test.ts
index ff54325ed..3655e9c96 100644
--- a/src/engine/core/utils/game/game_save.test.ts
+++ b/src/engine/core/utils/game/game_save.test.ts
@@ -1,4 +1,4 @@
-import { beforeEach, describe, expect, it } from "@jest/globals";
+import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import {
createAutoSave,
@@ -6,7 +6,10 @@ import {
deleteGameSave,
getFileDataForGameSave,
isGameSaveFileExist,
+ loadDynamicGameSave,
+ saveDynamicGameSave,
} from "@/engine/core/utils/game/game_save";
+import { MockIoFile } from "@/fixtures/lua";
import { resetFunctionMock } from "@/fixtures/utils";
import { gameConsole, MockFileSystem, MockFileSystemList, mocksConfig } from "@/fixtures/xray";
@@ -14,6 +17,7 @@ describe("'game_save' utils", () => {
beforeEach(() => {
resetFunctionMock(gameConsole.execute);
resetFunctionMock(gameConsole.get_float);
+ resetFunctionMock(io.open);
});
it("'getFileDataForGameSave' should correctly get save data", () => {
@@ -48,7 +52,8 @@ describe("'game_save' utils", () => {
MockFileSystem.getInstance().file_list_open_ex.mockImplementation(() => new MockFileSystemList(["a"]));
deleteGameSave("another");
expect(fileSystem.file_delete).toHaveBeenNthCalledWith(1, "$game_saves$", "another.scop");
- expect(fileSystem.file_delete).toHaveBeenNthCalledWith(2, "$game_saves$", "another.dds");
+ expect(fileSystem.file_delete).toHaveBeenNthCalledWith(2, "$game_saves$", "another.scopx");
+ expect(fileSystem.file_delete).toHaveBeenNthCalledWith(3, "$game_saves$", "another.dds");
});
it("'createSave' should correctly generate commands", () => {
@@ -92,4 +97,51 @@ describe("'game_save' utils", () => {
expect(() => createSave(null)).toThrow();
});
+
+ it("'saveDynamicGameSave' should correctly create dynamic file saves", () => {
+ const file: MockIoFile = new MockIoFile("test", "wb");
+
+ jest.spyOn(io, "open").mockImplementation(() => $multi(file.asMock()));
+
+ saveDynamicGameSave("example.scop", { a: 1, b: 2, c: 3 });
+
+ expect(lfs.mkdir).toHaveBeenCalledTimes(1);
+ expect(io.open).toHaveBeenCalledWith("$game_saves$example.scopx", "wb");
+ expect(file.write).toHaveBeenCalledWith(JSON.stringify({ a: 1, b: 2, c: 3 }));
+ expect(file.close).toHaveBeenCalledTimes(1);
+
+ expect(file.content).toBe(JSON.stringify({ a: 1, b: 2, c: 3 }));
+
+ file.isOpen = false;
+ saveDynamicGameSave("example.scop", { a: 1000 });
+
+ expect(file.write).toHaveBeenCalledTimes(1);
+ expect(file.content).toBe(JSON.stringify({ a: 1, b: 2, c: 3 }));
+ expect(file.close).toHaveBeenCalledTimes(1);
+ });
+
+ it("'loadDynamicGameSave' should correctly load dynamic file saves", () => {
+ const file: MockIoFile = new MockIoFile("test", "wb");
+
+ file.content = JSON.stringify({ a: 1, b: 33 });
+
+ jest.spyOn(io, "open").mockImplementation(() => $multi(file.asMock()));
+
+ expect(loadDynamicGameSave("F:\\\\parent\\\\example.scop")).toEqual({ a: 1, b: 33 });
+
+ expect(marshal.decode).toHaveBeenCalledWith(file.content);
+ expect(io.open).toHaveBeenCalledWith("F:\\\\parent\\\\example.scopx", "rb");
+ expect(file.read).toHaveBeenCalledTimes(1);
+ expect(file.close).toHaveBeenCalledTimes(1);
+
+ file.content = "";
+ expect(loadDynamicGameSave("F:\\\\parent\\\\example.scop")).toBeNull();
+
+ file.content = null;
+ expect(loadDynamicGameSave("F:\\\\parent\\\\example.scop")).toBeNull();
+
+ file.content = "{}";
+ file.isOpen = false;
+ expect(loadDynamicGameSave("F:\\\\parent\\\\example.scop")).toBeNull();
+ });
});
diff --git a/src/engine/core/utils/game/game_save.ts b/src/engine/core/utils/game/game_save.ts
index 5c0a2642c..2a54c6f65 100644
--- a/src/engine/core/utils/game/game_save.ts
+++ b/src/engine/core/utils/game/game_save.ts
@@ -8,7 +8,7 @@ import { gameConfig } from "@/engine/lib/configs/GameConfig";
import { captions } from "@/engine/lib/constants/captions";
import { consoleCommands } from "@/engine/lib/constants/console_commands";
import { roots } from "@/engine/lib/constants/roots";
-import { FSFileListEX, Optional, SavedGameWrapper, TCount, TLabel, TName } from "@/engine/lib/types";
+import { AnyObject, FSFileListEX, Optional, SavedGameWrapper, TCount, TLabel, TName, TPath } from "@/engine/lib/types";
const logger: LuaLogger = new LuaLogger($filename);
@@ -34,15 +34,76 @@ export function isGameSaveFileExist(filename: TName): boolean {
* @param filename - target name to delete from saves folder
*/
export function deleteGameSave(filename: TName): void {
- const saveFileName: TName = filename + gameConfig.GAME_SAVE_EXTENSION;
- const ddsFile: TName = filename + gameConfig.GAME_SAVE_PREVIEW_EXTENSION;
+ const saveBaseFile: TName = filename + gameConfig.GAME_SAVE_EXTENSION;
+ const saveDynamicFile: TName = filename + gameConfig.GAME_SAVE_DYNAMIC_EXTENSION;
+ const savePreviewFile: TName = filename + gameConfig.GAME_SAVE_PREVIEW_EXTENSION;
const fs: FS = getFS();
- fs.file_delete(roots.gameSaves, saveFileName);
+ logger.info("Delete game save:", filename);
- if (isGameSaveFileExist(ddsFile)) {
- fs.file_delete(roots.gameSaves, ddsFile);
+ fs.file_delete(roots.gameSaves, saveBaseFile);
+
+ // Delete dynamic base.
+ if (isGameSaveFileExist(saveDynamicFile)) {
+ fs.file_delete(roots.gameSaves, saveDynamicFile);
+ }
+
+ // Delete preview.
+ if (isGameSaveFileExist(savePreviewFile)) {
+ fs.file_delete(roots.gameSaves, savePreviewFile);
+ }
+}
+
+/**
+ * Create dynamic game save based on stringified binary data.
+ *
+ * @param filename - target save filename base to create or overwrite it
+ * @param data - data to save
+ */
+export function saveDynamicGameSave(filename: TName, data: AnyObject): void {
+ const savesFolder: TPath = getFS().update_path(roots.gameSaves, "");
+ const saveFile: TPath =
+ savesFolder + string.lower(string.sub(filename, 0, -6)) + gameConfig.GAME_SAVE_DYNAMIC_EXTENSION;
+
+ // Make sure saves directory exists.
+ lfs.mkdir(savesFolder);
+
+ const [existingSave] = io.open(saveFile, "wb");
+
+ if (!existingSave || io.type(existingSave) !== "file") {
+ return logger.error("Cannot write to save path:", saveFile);
+ }
+
+ existingSave.write(marshal.encode(data));
+ existingSave.close();
+}
+
+/**
+ * Read dynamic game save with stringified binary data.
+ *
+ * @param filename - target save filename full path
+ * @returns stringified binary data or null
+ */
+export function loadDynamicGameSave(filename: TName): Optional {
+ const saveFile: TPath = string.sub(filename, 0, -6) + gameConfig.GAME_SAVE_DYNAMIC_EXTENSION;
+
+ const [existingSave] = io.open(saveFile, "rb");
+
+ if (!existingSave || io.type(existingSave) !== "file") {
+ return null;
+ }
+
+ const data: Optional = existingSave.read("*all" as unknown as "*a") as Optional;
+
+ existingSave.close();
+
+ if (data && data !== "") {
+ return marshal.decode(data);
+ } else {
+ logger.warn("Was not able to read dynamic game save:", filename);
+
+ return null;
}
}
diff --git a/src/engine/core/utils/ini/ini_config.ts b/src/engine/core/utils/ini/ini_config.ts
index a32e66840..00a82ad4c 100644
--- a/src/engine/core/utils/ini/ini_config.ts
+++ b/src/engine/core/utils/ini/ini_config.ts
@@ -285,6 +285,9 @@ export function getConfigSwitchConditions(ini: IniFile, section: TSection): Opti
const linesCount: TCount = ini.line_count(section);
let index: TIndex = 1;
+ /**
+ * todo;
+ */
function addConditions(
func: (ini: IniFile, section: TSection, id: TStringId) => Optional,
cond: ESchemeCondition
diff --git a/src/engine/core/utils/object/object_anomaly.test.ts b/src/engine/core/utils/object/object_anomaly.test.ts
new file mode 100644
index 000000000..0966ad833
--- /dev/null
+++ b/src/engine/core/utils/object/object_anomaly.test.ts
@@ -0,0 +1,58 @@
+import { describe, expect, it } from "@jest/globals";
+
+import { registry } from "@/engine/core/database";
+import { AnomalyZoneBinder } from "@/engine/core/objects";
+import { anomalyHasArtefact, getAnomalyArtefacts } from "@/engine/core/utils/object/object_anomaly";
+import { mockClientGameObject, mockServerAlifeObject } from "@/fixtures/xray";
+
+describe("'object_anomaly' utils", () => {
+ it("'anomalyHasArtefact' should correctly check if anomaly has artefact", () => {
+ expect(anomalyHasArtefact("another", "")).toBe(false);
+ expect(anomalyHasArtefact("test-anomaly", "")).toBe(false);
+ expect(anomalyHasArtefact("test-anomaly", "sect_1")).toBe(false);
+
+ const anomalyZoneBinder: AnomalyZoneBinder = new AnomalyZoneBinder(mockClientGameObject());
+
+ registry.anomalyZones.set("test-anomaly", anomalyZoneBinder);
+ expect(anomalyHasArtefact("test-anomaly", "sect_1")).toBe(false);
+
+ anomalyZoneBinder.spawnedArtefactsCount = 3;
+ expect(anomalyHasArtefact("test-anomaly", "sect_1")).toBe(false);
+
+ anomalyZoneBinder.artefactWaysByArtefactId.set(511, "sect_1");
+ anomalyZoneBinder.artefactWaysByArtefactId.set(512, "sect_2");
+ anomalyZoneBinder.artefactWaysByArtefactId.set(513, "sect_3");
+ expect(anomalyHasArtefact("test-anomaly", "sect_1")).toBe(false);
+
+ mockServerAlifeObject({ id: 511, section_name: () => "sect_1" as T });
+ mockServerAlifeObject({ id: 512, section_name: () => "sect_2" as T });
+
+ expect(anomalyHasArtefact("test-anomaly", "sect_1")).toBe(true);
+ expect(anomalyHasArtefact("test-anomaly", "sect_2")).toBe(true);
+ expect(anomalyHasArtefact("test-anomaly", "sect_3")).toBe(false);
+ });
+
+ it("'getAnomalyArtefacts' should correctly get anomaly artefacts list", () => {
+ expect(getAnomalyArtefacts("another")).toEqualLuaArrays([]);
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays([]);
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays([]);
+
+ const anomalyZoneBinder: AnomalyZoneBinder = new AnomalyZoneBinder(mockClientGameObject());
+
+ registry.anomalyZones.set("another-anomaly", anomalyZoneBinder);
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays([]);
+
+ anomalyZoneBinder.spawnedArtefactsCount = 3;
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays([]);
+
+ anomalyZoneBinder.artefactWaysByArtefactId.set(521, "sect_1");
+ anomalyZoneBinder.artefactWaysByArtefactId.set(522, "sect_2");
+ anomalyZoneBinder.artefactWaysByArtefactId.set(523, "sect_3");
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays([]);
+
+ mockServerAlifeObject({ id: 521, section_name: () => "sect_1" as T });
+ mockServerAlifeObject({ id: 523, section_name: () => "sect_3" as T });
+
+ expect(getAnomalyArtefacts("another-anomaly")).toEqualLuaArrays(["sect_1", "sect_3"]);
+ });
+});
diff --git a/src/engine/core/utils/object/object_anomaly.ts b/src/engine/core/utils/object/object_anomaly.ts
index dd1b75b77..45f6bb6c9 100644
--- a/src/engine/core/utils/object/object_anomaly.ts
+++ b/src/engine/core/utils/object/object_anomaly.ts
@@ -2,49 +2,50 @@ import { alife } from "xray16";
import { registry } from "@/engine/core/database";
import { AnomalyZoneBinder } from "@/engine/core/objects";
-import { ClientObject, LuaArray, Optional, ServerObject, TName } from "@/engine/lib/types";
+import { LuaArray, Optional, ServerObject, TName, TSection } from "@/engine/lib/types";
/**
- * todo;
+ * @param anomalyZoneName - name of anomaly zone to check
+ * @param artefactSection - name of artefact to search in the anomaly
+ * @returns whether anomaly has artefact
*/
-export function anomalyHasArtefact(
- actor: ClientObject,
- object: Optional,
- anomalyZoneName: TName,
- artefactName: Optional
-): LuaMultiReturn<[boolean, Optional>]> {
- const anomalyZone: AnomalyZoneBinder = registry.anomalyZones.get(anomalyZoneName);
-
- if (anomalyZone === null) {
- return $multi(false, null);
- }
+export function anomalyHasArtefact(anomalyZoneName: TName, artefactSection: TSection): boolean {
+ const anomalyZone: Optional = registry.anomalyZones.get(anomalyZoneName);
- if (anomalyZone.spawnedArtefactsCount < 1) {
- return $multi(false, null);
+ if (!anomalyZone || anomalyZone.spawnedArtefactsCount < 1) {
+ return false;
}
- if (artefactName === null) {
- const artefactsList: LuaArray = new LuaTable();
-
- for (const [k, v] of registry.artefacts.ways) {
- const artefactObject: Optional = alife().object(tonumber(k)!);
+ for (const [artefactId] of anomalyZone.artefactWaysByArtefactId) {
+ const object: Optional = alife().object(artefactId);
- if (artefactObject) {
- table.insert(artefactsList, artefactObject.section_name());
- }
+ if (object && object.section_name() === artefactSection) {
+ return true;
}
+ }
+
+ return false;
+}
- return $multi(true, artefactsList);
+/**
+ * @param anomalyZoneName - name of anomaly zone to check
+ * @returns list of artefacts in the anomaly
+ */
+export function getAnomalyArtefacts(anomalyZoneName: TName): LuaArray {
+ const anomalyZone: Optional = registry.anomalyZones.get(anomalyZoneName);
+ const artefactsList: LuaArray = new LuaTable();
+
+ if (!anomalyZone || anomalyZone.spawnedArtefactsCount < 1) {
+ return artefactsList;
}
- for (const [artefactId] of registry.artefacts.ways) {
- if (
- alife().object(tonumber(artefactId)!) &&
- artefactName === alife().object(tonumber(artefactId)!)!.section_name()
- ) {
- return $multi(true, null);
+ for (const [artefactId] of anomalyZone.artefactWaysByArtefactId) {
+ const artefactObject: Optional = alife().object(artefactId);
+
+ if (artefactObject) {
+ table.insert(artefactsList, artefactObject.section_name());
}
}
- return $multi(false, null);
+ return artefactsList;
}
diff --git a/src/engine/core/utils/object/object_danger.test.ts b/src/engine/core/utils/object/object_danger.test.ts
new file mode 100644
index 000000000..21e69d287
--- /dev/null
+++ b/src/engine/core/utils/object/object_danger.test.ts
@@ -0,0 +1,212 @@
+import { describe, expect, it, jest } from "@jest/globals";
+import { danger_object } from "xray16";
+
+import { IRegistryObjectState, registerObject, registry } from "@/engine/core/database";
+import { SimulationBoardManager } from "@/engine/core/managers/interaction/SimulationBoardManager";
+import { SmartTerrain, SmartTerrainControl } from "@/engine/core/objects";
+import { ESmartTerrainStatus } from "@/engine/core/objects/server/smart_terrain/types";
+import { ISchemeCombatIgnoreState } from "@/engine/core/schemes/combat_ignore";
+import { ISchemeWoundedState } from "@/engine/core/schemes/wounded";
+import { WoundManager } from "@/engine/core/schemes/wounded/WoundManager";
+import { parseConditionsList } from "@/engine/core/utils/ini";
+import { canObjectSelectAsEnemy, isObjectFacingDanger } from "@/engine/core/utils/object/object_danger";
+import { classIds } from "@/engine/lib/constants/class_ids";
+import { FALSE, TRUE } from "@/engine/lib/constants/words";
+import { ClientObject, EClientObjectRelation, EScheme, ServerSmartZoneObject, TClassId } from "@/engine/lib/types";
+import { mockSchemeState } from "@/fixtures/engine";
+import { replaceFunctionMock } from "@/fixtures/utils";
+import {
+ mockClientGameObject,
+ MockDangerObject,
+ mockServerAlifeHumanStalker,
+ mockServerAlifeObject,
+ mockServerAlifeSmartZone,
+} from "@/fixtures/xray";
+
+describe("'object_danger' utils", () => {
+ it("'isObjectFacingDanger' should correctly check generic danger", () => {
+ expect(isObjectFacingDanger(mockClientGameObject())).toBe(false);
+
+ const object: ClientObject = mockClientGameObject();
+ const bestDanger: MockDangerObject = new MockDangerObject();
+ const state: IRegistryObjectState = registerObject(object);
+
+ state[EScheme.COMBAT_IGNORE] = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+ replaceFunctionMock(object.best_danger, () => bestDanger);
+
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ bestDanger.dangerDependentObject = mockClientGameObject();
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ replaceFunctionMock(object.relation, () => EClientObjectRelation.ENEMY);
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ bestDanger.dangerType = danger_object.hit;
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 150 * 150);
+ expect(isObjectFacingDanger(object)).toBe(true);
+ });
+
+ it("'isObjectFacingDanger' should correctly check generic danger", () => {
+ expect(isObjectFacingDanger(mockClientGameObject())).toBe(false);
+
+ const object: ClientObject = mockClientGameObject();
+ const bestDanger: MockDangerObject = new MockDangerObject();
+ const state: IRegistryObjectState = registerObject(object);
+
+ state[EScheme.COMBAT_IGNORE] = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+ replaceFunctionMock(object.best_danger, () => bestDanger);
+
+ bestDanger.dangerDependentObject = mockClientGameObject();
+ replaceFunctionMock(object.relation, () => EClientObjectRelation.ENEMY);
+ bestDanger.dangerType = danger_object.hit;
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 150 * 150);
+
+ jest.spyOn(object, "alive").mockImplementation(() => false);
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ jest.spyOn(object, "alive").mockImplementation(() => true);
+ expect(isObjectFacingDanger(object)).toBe(true);
+ });
+
+ it("'isObjectFacingDanger' should correctly ignore corpses", () => {
+ const object: ClientObject = mockClientGameObject();
+ const bestDanger: MockDangerObject = new MockDangerObject();
+ const state: IRegistryObjectState = registerObject(object);
+
+ state[EScheme.COMBAT_IGNORE] = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+ replaceFunctionMock(object.best_danger, () => bestDanger);
+
+ bestDanger.dangerType = danger_object.entity_corpse;
+ expect(isObjectFacingDanger(object)).toBe(false);
+ });
+
+ it("'isObjectFacingDanger' should correctly check ignore distance", () => {
+ const object: ClientObject = mockClientGameObject();
+ const bestDanger: MockDangerObject = new MockDangerObject();
+ const state: IRegistryObjectState = registerObject(object);
+
+ state[EScheme.COMBAT_IGNORE] = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+ replaceFunctionMock(object.best_danger, () => bestDanger);
+
+ bestDanger.dangerType = danger_object.entity_death;
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 100);
+ expect(isObjectFacingDanger(object)).toBe(true);
+
+ bestDanger.dangerType = danger_object.entity_death;
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 101);
+ expect(isObjectFacingDanger(object)).toBe(false);
+ });
+
+ it("'isObjectFacingDanger' should correctly check grenades", () => {
+ const object: ClientObject = mockClientGameObject({ clsid: () => classIds.script_stalker as TClassId });
+ const bestDanger: MockDangerObject = new MockDangerObject();
+ const state: IRegistryObjectState = registerObject(object);
+
+ state[EScheme.COMBAT_IGNORE] = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+ bestDanger.dangerType = danger_object.grenade;
+ replaceFunctionMock(object.best_danger, () => bestDanger);
+
+ // Out of range.
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 226);
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ // In range.
+ jest.spyOn(bestDanger.dangerPosition, "distance_to_sqr").mockImplementation(() => 225);
+ expect(isObjectFacingDanger(object)).toBe(true);
+
+ // When zombied.
+ jest.spyOn(object, "character_community").mockImplementation(() => "zombied");
+ expect(isObjectFacingDanger(object)).toBe(false);
+
+ // When stalker.
+ jest.spyOn(object, "character_community").mockImplementation(() => "stalker");
+ expect(isObjectFacingDanger(object)).toBe(true);
+
+ // When injured.
+ state[EScheme.WOUNDED] = mockSchemeState(object, EScheme.WOUNDED, {
+ woundManager: { woundState: "true" } as WoundManager,
+ });
+ expect(isObjectFacingDanger(object)).toBe(false);
+ });
+
+ it("'canObjectSelectAsEnemy' should correctly check enemies selection possibility", () => {
+ const object: ClientObject = mockClientGameObject({ clsid: () => classIds.script_stalker as TClassId });
+ const enemy: ClientObject = mockClientGameObject();
+ const state: IRegistryObjectState = registerObject(object);
+ const combatIgnoreState: ISchemeCombatIgnoreState = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+
+ state[EScheme.COMBAT_IGNORE] = combatIgnoreState;
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(true);
+ expect(state.enemy_id).toBe(enemy.id());
+
+ state.enemy_id = null;
+ jest.spyOn(object, "alive").mockImplementationOnce(() => false);
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(false);
+ expect(state.enemy_id).toBeNull();
+
+ expect(canObjectSelectAsEnemy(mockClientGameObject(), enemy, null as unknown as ISchemeCombatIgnoreState)).toBe(
+ true
+ );
+
+ state.enemy_id = null;
+ combatIgnoreState.overrides = {
+ combat_ignore: {
+ condlist: parseConditionsList(TRUE),
+ },
+ };
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(false);
+ expect(state.enemy_id).toBe(enemy.id());
+
+ state.enemy_id = null;
+ combatIgnoreState.overrides = {
+ combat_ignore: {
+ condlist: parseConditionsList(FALSE),
+ },
+ };
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(true);
+ expect(state.enemy_id).toBe(enemy.id());
+ });
+
+ it("'canObjectSelectAsEnemy' should correctly check enemies in no-combat zones", () => {
+ const object: ClientObject = mockClientGameObject({ clsid: () => classIds.script_stalker as TClassId });
+ const enemy: ClientObject = mockClientGameObject();
+ const state: IRegistryObjectState = registerObject(object);
+ const combatIgnoreState: ISchemeCombatIgnoreState = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+
+ const noCombatZone: ClientObject = mockClientGameObject();
+ const noCombatSmart: ServerSmartZoneObject = mockServerAlifeSmartZone({
+ name: () => "zat_stalker_base_smart" as T,
+ });
+
+ state[EScheme.COMBAT_IGNORE] = combatIgnoreState;
+
+ registry.zones.set("zat_a2_sr_no_assault", noCombatZone);
+ jest.spyOn(noCombatZone, "inside").mockImplementation(() => true);
+ SimulationBoardManager.getInstance().registerSmartTerrain(noCombatSmart as SmartTerrain);
+
+ (noCombatSmart as SmartTerrain).smartTerrainActorControl = {
+ status: ESmartTerrainStatus.NORMAL,
+ } as SmartTerrainControl;
+
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(false);
+ expect(state.enemy_id).toBe(enemy.id());
+ });
+
+ it("'canObjectSelectAsEnemy' should correctly ignore enemies in no-combat smarts", () => {
+ const object: ClientObject = mockClientGameObject({ clsid: () => classIds.script_stalker as TClassId });
+ const enemy: ClientObject = mockClientGameObject();
+ const state: IRegistryObjectState = registerObject(object);
+ const combatIgnoreState: ISchemeCombatIgnoreState = mockSchemeState(object, EScheme.COMBAT_IGNORE);
+
+ const noCombatSmart: ServerSmartZoneObject = mockServerAlifeSmartZone({
+ name: () => "zat_stalker_base_smart" as T,
+ });
+
+ mockServerAlifeHumanStalker({ id: enemy.id(), m_smart_terrain_id: noCombatSmart.id });
+
+ state[EScheme.COMBAT_IGNORE] = combatIgnoreState;
+ expect(canObjectSelectAsEnemy(object, enemy, combatIgnoreState)).toBe(false);
+ expect(state.enemy_id).toBe(enemy.id());
+ });
+});
diff --git a/src/engine/core/utils/object/object_danger.ts b/src/engine/core/utils/object/object_danger.ts
index ded65502c..6f4a427b1 100644
--- a/src/engine/core/utils/object/object_danger.ts
+++ b/src/engine/core/utils/object/object_danger.ts
@@ -28,11 +28,15 @@ import {
} from "@/engine/lib/types";
/**
+ * Check whether object is facing any danger.
+ *
+ * @param object - target client object to check
* @returns whether object is facing any danger right now
*/
export function isObjectFacingDanger(object: ClientObject): boolean {
const bestDanger: Optional = object.best_danger();
+ // No danger at all.
if (bestDanger === null) {
return false;
}
@@ -43,28 +47,16 @@ export function isObjectFacingDanger(object: ClientObject): boolean {
? bestDanger.dependent_object()
: bestDanger.object();
+ // No danger source object.
if (bestDangerObject === null) {
return false;
}
- if (
- bestDangerType !== danger_object.entity_corpse &&
- bestDangerType !== danger_object.grenade &&
- object.relation(bestDangerObject) !== EClientObjectRelation.ENEMY
- ) {
- return false;
- }
-
- if (bestDangerType === danger_object.grenade) {
- // Zombied ignore grenades.
- if (getObjectCommunity(object) === communities.zombied) {
- return false;
- }
- }
-
- // todo: Implement?
+ // Ignore corpses.
if (bestDangerType === danger_object.entity_corpse) {
return false;
+ // todo: Implement?
+
/**
* --const corpse_object = best_danger:object()
* --if time_global() - corpse_object:death_time() >= DANGER_INERTION_TIME then
@@ -73,8 +65,23 @@ export function isObjectFacingDanger(object: ClientObject): boolean {
*/
}
+ // Zombied ignore grenades.
+ if (bestDangerType === danger_object.grenade && getObjectCommunity(object) === communities.zombied) {
+ return false;
+ }
+
+ // Verify relation of enemy object. Handle friendly grenades and death.
+ if (
+ bestDangerType !== danger_object.grenade &&
+ bestDangerType !== danger_object.entity_death &&
+ object.relation(bestDangerObject) !== EClientObjectRelation.ENEMY
+ ) {
+ return false;
+ }
+
+ // Verify if object is not enemy at all.
if (
- !isObjectEnemy(
+ !canObjectSelectAsEnemy(
object,
bestDangerObject,
registry.objects.get(object.id())[EScheme.COMBAT_IGNORE] as ISchemeCombatIgnoreState
@@ -85,18 +92,17 @@ export function isObjectFacingDanger(object: ClientObject): boolean {
const dangerDistanceSqrt: TDistance = bestDanger.position().distance_to_sqr(object.position());
const ignoreDistanceByType: Optional = logicsConfig.DANGER_IGNORE_DISTANCE_BY_TYPE[bestDangerType];
+ const ignoreDistance: TDistance =
+ ignoreDistanceByType === null
+ ? logicsConfig.DANGER_IGNORE_DISTANCE_GENERAL * logicsConfig.DANGER_IGNORE_DISTANCE_GENERAL
+ : ignoreDistanceByType * ignoreDistanceByType;
- if (ignoreDistanceByType !== null) {
- if (dangerDistanceSqrt >= ignoreDistanceByType * ignoreDistanceByType) {
- return false;
- }
- } else if (
- dangerDistanceSqrt >=
- logicsConfig.DANGER_IGNORE_DISTANCE_GENERAL * logicsConfig.DANGER_IGNORE_DISTANCE_GENERAL
- ) {
+ // Verify danger distance.
+ if (dangerDistanceSqrt > ignoreDistance) {
return false;
}
+ // Verify if object is wounded and cannot react to danger.
if (isObjectWounded(object.id())) {
return false;
}
@@ -112,43 +118,56 @@ export function isObjectFacingDanger(object: ClientObject): boolean {
}
/**
- * todo;
+ * Check whether object is valid enemy of another object.
+ *
+ * @param object - target object to check
+ * @param enemy - possible enemy to check
+ * @param combatIgnoreState - state of combat ignore state scheme
* @returns whether object os enemy of provided client entity
*/
-export function isObjectEnemy(object: ClientObject, enemy: ClientObject, state: ISchemeCombatIgnoreState): boolean {
+export function canObjectSelectAsEnemy(
+ object: ClientObject,
+ enemy: ClientObject,
+ combatIgnoreState: ISchemeCombatIgnoreState
+): boolean {
+ // Dead, cannot select enemies.
if (!object.alive()) {
return false;
}
- if (object.critically_wounded()) {
- return true;
- }
+ const objectState: Optional = registry.objects.get(object.id());
- if (state.enabled === false) {
+ if (objectState === null) {
return true;
}
- const overrides: Optional = state.overrides;
- const objectId: TNumberId = object.id();
- const objectState: IRegistryObjectState = registry.objects.get(objectId);
+ // todo: Probably also clean it up? And set only when 'true'
+ objectState.enemy_id = enemy.id();
- if (objectState === null) {
+ // When object is critically wounded, it should fight back.
+ if (object.critically_wounded()) {
return true;
}
- objectState.enemy_id = enemy.id();
+ // Combat ignoring is explicitly disabled.
+ if (combatIgnoreState.enabled === false) {
+ return true;
+ }
if (enemy.id() !== ACTOR_ID) {
- for (const [k, v] of registry.noCombatZones) {
- const zone = registry.zones.get(k);
+ // If enemy of object is in no-combat zone.
+ for (const [name, storyId] of registry.noCombatZones) {
+ const zone: Optional = registry.zones.get(name);
if (zone && (isObjectInZone(object, zone) || isObjectInZone(enemy, zone))) {
- const smart: Optional = SimulationBoardManager.getInstance().getSmartTerrainByName(v);
+ const smartTerrain: Optional =
+ SimulationBoardManager.getInstance().getSmartTerrainByName(storyId);
+ // Still allow combat if zone is set to alarm.
if (
- smart &&
- smart.smartTerrainActorControl !== null &&
- smart.smartTerrainActorControl.status !== ESmartTerrainStatus.ALARM
+ smartTerrain &&
+ smartTerrain.smartTerrainActorControl !== null &&
+ smartTerrain.smartTerrainActorControl.status !== ESmartTerrainStatus.ALARM
) {
return false;
}
@@ -158,6 +177,7 @@ export function isObjectEnemy(object: ClientObject, enemy: ClientObject, state:
const serverObject: Optional = alife().object(enemy.id());
+ // Check if server object is in no-combat zone.
if (
serverObject !== null &&
serverObject.m_smart_terrain_id !== null &&
@@ -172,8 +192,11 @@ export function isObjectEnemy(object: ClientObject, enemy: ClientObject, state:
}
}
- if (overrides && overrides.combat_ignore) {
- return pickSectionFromCondList(enemy, object, overrides.combat_ignore.condlist) !== TRUE;
+ // Check if object have any state overrides that cause object to explicitly ignore combat.
+ const stateOverrides: Optional = combatIgnoreState.overrides;
+
+ if (stateOverrides && stateOverrides.combat_ignore) {
+ return pickSectionFromCondList(enemy, object, stateOverrides.combat_ignore.condlist) !== TRUE;
}
return true;
diff --git a/src/engine/core/utils/object/object_find.ts b/src/engine/core/utils/object/object_find.ts
index 7cee019ef..815c2fac6 100644
--- a/src/engine/core/utils/object/object_find.ts
+++ b/src/engine/core/utils/object/object_find.ts
@@ -3,6 +3,7 @@ import { alife, level } from "xray16";
import { registry } from "@/engine/core/database";
import { LuaLogger } from "@/engine/core/utils/logging";
import { areObjectsOnSameLevel } from "@/engine/core/utils/object/object_location";
+import { ACTOR_ID } from "@/engine/lib/constants/ids";
import {
AlifeSimulator,
AnyCallable,
@@ -141,7 +142,7 @@ export function getNearestClientObject(
let nearest: Optional = null;
level.iterate_online_objects((object: ClientObject): void => {
- if (object.parent() !== registry.actor) {
+ if (object.id() !== ACTOR_ID && object.parent()?.id() !== ACTOR_ID) {
let isMatch: boolean = false;
// Filter objects if pattern is provided.
@@ -187,17 +188,17 @@ export function getClientObjects(
): LuaArray {
const list: LuaArray = new LuaTable();
- level.iterate_online_objects((clientObject: ClientObject) => {
- if (clientObject.parent() !== registry.actor) {
+ level.iterate_online_objects((object: ClientObject) => {
+ if (object.id() !== ACTOR_ID && object.parent()?.id() !== ACTOR_ID) {
let isMatch: boolean = false;
// Filter objects if pattern is provided.
if (pattern !== null) {
- if (type(pattern) === "string" && string.find(clientObject.name(), pattern as string)[0]) {
+ if (type(pattern) === "string" && string.find(object.name(), pattern as string)[0]) {
isMatch = true;
- } else if (type(pattern) === "number" && pattern === clientObject.clsid()) {
+ } else if (type(pattern) === "number" && pattern === object.clsid()) {
isMatch = true;
- } else if (type(pattern) === "function" && (pattern as AnyCallable)(clientObject)) {
+ } else if (type(pattern) === "function" && (pattern as AnyCallable)(object)) {
isMatch = true;
}
} else {
@@ -206,7 +207,7 @@ export function getClientObjects(
// Validate match and online-offline check.
if (isMatch) {
- table.insert(list, clientObject);
+ table.insert(list, object);
}
}
});
diff --git a/src/engine/core/utils/scheme/scheme_initialization.test.ts b/src/engine/core/utils/scheme/scheme_initialization.test.ts
index 4af38b40c..3e4f7de2d 100644
--- a/src/engine/core/utils/scheme/scheme_initialization.test.ts
+++ b/src/engine/core/utils/scheme/scheme_initialization.test.ts
@@ -138,7 +138,7 @@ describe("'scheme initialization' utils", () => {
jest.spyOn(it, "reset").mockImplementation(() => {});
});
- jest.spyOn(smartTerrain, "getJob").mockImplementation(() => ({ ini_path: "job_test.ltx" } as ISmartTerrainJob));
+ jest.spyOn(smartTerrain, "getJob").mockImplementation(() => ({ ini_path: "job_test.ltx" }) as ISmartTerrainJob);
resetFunctionMock(alife().create);
diff --git a/src/engine/core/utils/scheme/scheme_logic.test.ts b/src/engine/core/utils/scheme/scheme_logic.test.ts
index 644dc480e..3903b29d6 100644
--- a/src/engine/core/utils/scheme/scheme_logic.test.ts
+++ b/src/engine/core/utils/scheme/scheme_logic.test.ts
@@ -50,6 +50,9 @@ import { MockAlifeSimulator, mockClientGameObject, mockIniFile, mockServerAlifeH
import { MockCTime } from "@/fixtures/xray/mocks/CTime.mock";
describe("'scheme logic' utils", () => {
+ /**
+ * todo;
+ */
function loadGenericSchemes(): Array {
const schemes: Array = [
SchemeMeet,
@@ -212,7 +215,7 @@ describe("'scheme logic' utils", () => {
() =>
({
section: "patrol@test",
- } as ISmartTerrainJob)
+ }) as ISmartTerrainJob
);
const ini: IniFile = mockIniFile("test.ltx", {
diff --git a/src/engine/core/utils/transform/decamelize.ts b/src/engine/core/utils/transform/decamelize.ts
index 3daacdb2c..debfb43e7 100644
--- a/src/engine/core/utils/transform/decamelize.ts
+++ b/src/engine/core/utils/transform/decamelize.ts
@@ -16,10 +16,6 @@ function handlePreserveConsecutiveUppercase(decamelized: string, separator: stri
/**
* Fork of NPM 'decamelize' package utility.
* Decamelize provided string.
- *
- * @param text - string value to decamelize
- * @param config - decamelize process parameters
- * @returns decamelized string
*/
export function decamelize(text: string, { separator = "_", preserveConsecutiveUppercase = false } = {}) {
if (text.length < 2) {
diff --git a/src/engine/core/utils/transform/json.test.ts b/src/engine/core/utils/transform/json.test.ts
index 7ae39ec1f..9ba58d797 100644
--- a/src/engine/core/utils/transform/json.test.ts
+++ b/src/engine/core/utils/transform/json.test.ts
@@ -1,11 +1,11 @@
-import { describe, expect, it } from "@jest/globals";
+import { describe, expect, it, jest } from "@jest/globals";
import { quoted } from "#/utils";
-import { toJSON } from "@/engine/core/utils/transform/json";
+import { stringifyKey, toJSON } from "@/engine/core/utils/transform/json";
describe("'json' util", () => {
- it("should correctly stringify simple types", () => {
+ it("'toJSON' should correctly stringify simple types", () => {
expect(toJSON("abc")).toBe(quoted("abc"));
expect(toJSON("bca")).toBe(quoted("bca"));
expect(toJSON(123)).toBe("123");
@@ -16,7 +16,7 @@ describe("'json' util", () => {
expect(toJSON(undefined)).toBe("");
});
- it("should correctly stringify tables", () => {
+ it("'toJSON' should correctly stringify tables", () => {
expect(toJSON({})).toBe("{}");
expect(toJSON({ a: 10 })).toBe(`{${quoted("a")}: 10}`);
expect(toJSON({ b: "ab", c: 5, d: false, e: null })).toBe(
@@ -25,7 +25,7 @@ describe("'json' util", () => {
expect(toJSON({ a: 10, b: { c: 1234 } })).toBe(`{${quoted("a")}: 10, "b": {"c": 1234}}`);
});
- it("should correctly stringify circular references", () => {
+ it("'toJSON' should correctly stringify circular references", () => {
const base = { nested: { circular: {} } };
base.nested.circular = base;
@@ -33,7 +33,7 @@ describe("'json' util", () => {
expect(toJSON(base)).toBe(`{${quoted("nested")}: {"circular": }}`);
});
- it("should correctly limit depth", () => {
+ it("'toJSON' should correctly limit depth", () => {
const base = { nested: { nested: { nested: { nested: {} } } } };
expect(toJSON(base, " ", 0, 3)).toBe(`{${quoted("nested")}: {"nested": {"nested": {"nested": }}}}`);
@@ -41,4 +41,27 @@ describe("'json' util", () => {
expect(toJSON(base, " ", 0, 1)).toBe(`{${quoted("nested")}: {"nested": }}`);
expect(toJSON(base, " ", 0, 0)).toBe(`{${quoted("nested")}: }`);
});
+
+ it("'toJSON' should correctly transform unusual non-table values", () => {
+ expect(toJSON(() => {})).toBe("");
+
+ jest.spyOn(global, "type").mockReturnValueOnce("userdata");
+ expect(toJSON({})).toBe("");
+
+ jest.spyOn(global, "type").mockReturnValueOnce("thread");
+ expect(toJSON({})).toBe("");
+ });
+
+ it("'stringifyKey' should correctly stringify json keys", () => {
+ expect(stringifyKey(123)).toBe("123");
+ expect(stringifyKey("abc")).toBe("abc");
+ expect(stringifyKey(true)).toBe("");
+ expect(stringifyKey(() => {})).toBe("");
+
+ jest.spyOn(global, "type").mockReturnValueOnce("userdata");
+ expect(stringifyKey({})).toBe("");
+
+ jest.spyOn(global, "type").mockReturnValueOnce("thread");
+ expect(stringifyKey({})).toBe("");
+ });
});
diff --git a/src/engine/core/utils/vector.ts b/src/engine/core/utils/vector.ts
index 0a03254ad..f545e3717 100644
--- a/src/engine/core/utils/vector.ts
+++ b/src/engine/core/utils/vector.ts
@@ -51,6 +51,8 @@ export function subVectors(first: Vector, second: Vector): Vector {
}
/**
+ * Cross-multiply vectors.
+ *
* @param first - vector to cross
* @param second - vector to cross
* @returns vectors cross multiplication result
@@ -74,6 +76,8 @@ export function copyVector(source: Vector): Vector {
}
/**
+ * Get vectors yaw.
+ *
* @param first - vector to compute
* @param second - vector to compute
* @returns vectors yaw
@@ -86,6 +90,8 @@ export function yaw(first: Vector, second: Vector): TRate {
}
/**
+ * Get vectors yaw degree.
+ *
* @param first - vector to compute
* @param second - vector to compute
* @returns vectors yaw degree
@@ -100,6 +106,8 @@ export function yawDegree(first: Vector, second: Vector): TRate {
}
/**
+ * Get vectors yaw degree in 3 dimensions.
+ *
* @param first - vector to compute
* @param second - vector to compute
* @returns vectors yaw degree in 3 dimensions
@@ -115,6 +123,8 @@ export function yawDegree3d(first: Vector, second: Vector): TRate {
}
/**
+ * Rotate vector by Y axis.
+ *
* @param target - vector to rotate
* @param angleBase - angle to rotate vector
* @returns new rotated vector
@@ -159,6 +169,8 @@ export function angleDiff(first: Vector, second: Vector): number {
}
/**
+ * Transform angle vector to direction vector.
+ *
* @param angle - angle vector
* @returns direction vector based on angle vector
*/
diff --git a/src/engine/forms/actor_menu.tsx b/src/engine/forms/actor_menu.tsx
index 12d6ce8ec..6e7d73f88 100644
--- a/src/engine/forms/actor_menu.tsx
+++ b/src/engine/forms/actor_menu.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { captions } from "@/engine/lib/constants/captions";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/actor_menu_16.tsx b/src/engine/forms/actor_menu_16.tsx
index 7dd119967..291e1f3ca 100644
--- a/src/engine/forms/actor_menu_16.tsx
+++ b/src/engine/forms/actor_menu_16.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { captions } from "@/engine/lib/constants/captions";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/actor_menu_item.tsx b/src/engine/forms/actor_menu_item.tsx
index 96d3a6a70..ce69c460f 100644
--- a/src/engine/forms/actor_menu_item.tsx
+++ b/src/engine/forms/actor_menu_item.tsx
@@ -3,6 +3,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { ArtefactParams } from "@/engine/forms/af_params";
import { BoosterParams } from "@/engine/forms/booster_params";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/actor_menu_item_16.tsx b/src/engine/forms/actor_menu_item_16.tsx
index f08e768d0..b8cd9283d 100644
--- a/src/engine/forms/actor_menu_item_16.tsx
+++ b/src/engine/forms/actor_menu_item_16.tsx
@@ -3,6 +3,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { ArtefactParams } from "@/engine/forms/af_params_16";
import { BoosterParams } from "@/engine/forms/booster_params_16";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/af_params.tsx b/src/engine/forms/af_params.tsx
index 294cdee13..f0a5454f6 100644
--- a/src/engine/forms/af_params.tsx
+++ b/src/engine/forms/af_params.tsx
@@ -1,9 +1,15 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
+/**
+ * todo;
+ */
export function ArtefactParams(): JSXNode {
return (
diff --git a/src/engine/forms/af_params_16.tsx b/src/engine/forms/af_params_16.tsx
index 30e74882b..9d113ca62 100644
--- a/src/engine/forms/af_params_16.tsx
+++ b/src/engine/forms/af_params_16.tsx
@@ -1,9 +1,15 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
+/**
+ * todo;
+ */
export function ArtefactParams(): JSXNode {
return (
diff --git a/src/engine/forms/booster_params.tsx b/src/engine/forms/booster_params.tsx
index c1db4655f..73a834c03 100644
--- a/src/engine/forms/booster_params.tsx
+++ b/src/engine/forms/booster_params.tsx
@@ -4,10 +4,16 @@ import { XrComponent, XrText } from "@/engine/forms/components/base";
import { XrTexture } from "@/engine/forms/components/base/XrTexture.component";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
+/**
+ * todo;
+ */
export function BoosterParams(): JSXNode {
return (
@@ -41,6 +47,9 @@ export function BoosterParams(): JSXNode {
);
}
+/**
+ * todo;
+ */
function BoosterParam({
name,
texture,
diff --git a/src/engine/forms/booster_params_16.tsx b/src/engine/forms/booster_params_16.tsx
index e33279cce..8073edea7 100644
--- a/src/engine/forms/booster_params_16.tsx
+++ b/src/engine/forms/booster_params_16.tsx
@@ -4,10 +4,16 @@ import { XrComponent, XrText } from "@/engine/forms/components/base";
import { XrTexture } from "@/engine/forms/components/base/XrTexture.component";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
+/**
+ * todo;
+ */
export function BoosterParams(): JSXNode {
return (
@@ -41,6 +47,9 @@ export function BoosterParams(): JSXNode {
);
}
+/**
+ *
+ */
function BoosterParam({
name,
texture,
diff --git a/src/engine/forms/buy_menu_item.tsx b/src/engine/forms/buy_menu_item.tsx
index bfe2ed691..9af08e21a 100644
--- a/src/engine/forms/buy_menu_item.tsx
+++ b/src/engine/forms/buy_menu_item.tsx
@@ -3,6 +3,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { ArtefactParams } from "@/engine/forms/af_params";
import { BoosterParams } from "@/engine/forms/booster_params";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/buy_menu_item_16.tsx b/src/engine/forms/buy_menu_item_16.tsx
index f1c89c659..3fa2f507e 100644
--- a/src/engine/forms/buy_menu_item_16.tsx
+++ b/src/engine/forms/buy_menu_item_16.tsx
@@ -3,6 +3,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { ArtefactParams } from "@/engine/forms/af_params_16";
import { BoosterParams } from "@/engine/forms/booster_params_16";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/chat_mp.tsx b/src/engine/forms/chat_mp.tsx
index c6874b04b..4c921a394 100644
--- a/src/engine/forms/chat_mp.tsx
+++ b/src/engine/forms/chat_mp.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/color_defs.tsx b/src/engine/forms/color_defs.tsx
index f61907f39..92da34557 100644
--- a/src/engine/forms/color_defs.tsx
+++ b/src/engine/forms/color_defs.tsx
@@ -1,6 +1,10 @@
import { JSXNode, JSXXML } from "jsx-xml";
// todo: Use enum with defined colors.
+
+/**
+ * todo;
+ */
export function create(): JSXNode {
//
//
diff --git a/src/engine/forms/components/base/XrBackground.component.tsx b/src/engine/forms/components/base/XrBackground.component.tsx
index afd9efc68..6ee21194d 100644
--- a/src/engine/forms/components/base/XrBackground.component.tsx
+++ b/src/engine/forms/components/base/XrBackground.component.tsx
@@ -8,6 +8,9 @@ export interface IXrBackgroundProps extends IBaseXmlNode {
stretch?: boolean;
}
+/**
+ * todo;
+ */
export function XrBackground(props: IXrBackgroundProps): JSXNode {
const { x, y, width, height, stretch } = normalizeBaseNodeProps(props);
diff --git a/src/engine/forms/components/base/XrCheckBox.component.tsx b/src/engine/forms/components/base/XrCheckBox.component.tsx
index 26d34d36d..138f5cbc3 100644
--- a/src/engine/forms/components/base/XrCheckBox.component.tsx
+++ b/src/engine/forms/components/base/XrCheckBox.component.tsx
@@ -16,6 +16,9 @@ export interface IXrCheckBoxProps extends IBaseXmlNode {
group?: string;
}
+/**
+ * todo;
+ */
export function XrCheckBox(props: IXrCheckBoxProps): JSXNode {
const {
tag = "check",
diff --git a/src/engine/forms/components/base/XrComponent.component.tsx b/src/engine/forms/components/base/XrComponent.component.tsx
index 168e0ba8f..a06a9ec33 100644
--- a/src/engine/forms/components/base/XrComponent.component.tsx
+++ b/src/engine/forms/components/base/XrComponent.component.tsx
@@ -6,6 +6,9 @@ import { IBaseXmlNode } from "@/engine/lib/types";
export interface IXrContainerProps extends IBaseXmlNode {}
+/**
+ * todo;
+ */
export function XrComponent(props: IXrContainerProps): JSXNode {
const { x, y, width, height, stretch } = normalizeBaseNodeProps(props);
diff --git a/src/engine/forms/components/base/XrEditBox.component.tsx b/src/engine/forms/components/base/XrEditBox.component.tsx
index d58c03a2a..7f8845bbc 100644
--- a/src/engine/forms/components/base/XrEditBox.component.tsx
+++ b/src/engine/forms/components/base/XrEditBox.component.tsx
@@ -17,6 +17,9 @@ export interface IXrEditBoxProps extends IBaseXmlNode {
maxSymbolsCount?: number;
}
+/**
+ * todo;
+ */
export function XrEditBox(props: IXrEditBoxProps): JSXNode {
const {
tag = "edit_box",
diff --git a/src/engine/forms/components/base/XrList.component.tsx b/src/engine/forms/components/base/XrList.component.tsx
index 80e75f494..e6a68fdb2 100644
--- a/src/engine/forms/components/base/XrList.component.tsx
+++ b/src/engine/forms/components/base/XrList.component.tsx
@@ -10,7 +10,9 @@ export interface IXrListComponentProps extends IBaseXmlNode {
itemHeight: number;
canSelect?: boolean;
}
-
+/**
+ * todo;
+ */
export function XrList(props: IXrListComponentProps): JSXNode {
const {
tag = "list",
diff --git a/src/engine/forms/components/base/XrListRenderer.component.tsx b/src/engine/forms/components/base/XrListRenderer.component.tsx
index 479164304..29e01fb28 100644
--- a/src/engine/forms/components/base/XrListRenderer.component.tsx
+++ b/src/engine/forms/components/base/XrListRenderer.component.tsx
@@ -7,6 +7,9 @@ import { IBaseXmlNode } from "@/engine/lib/types";
export interface IXrComboBoxProps extends IBaseXmlNode {}
+/**
+ * todo;
+ */
export function XrComboBox(props: IXrComboBoxProps): JSXNode {
const { tag = "list_renderer", x, y, width, height, children = null } = normalizeBaseNodeProps(props);
diff --git a/src/engine/forms/components/base/XrRoot.component.tsx b/src/engine/forms/components/base/XrRoot.component.tsx
index e6bb1dcd8..b612d1983 100644
--- a/src/engine/forms/components/base/XrRoot.component.tsx
+++ b/src/engine/forms/components/base/XrRoot.component.tsx
@@ -6,6 +6,9 @@ import { IBaseXmlNode } from "@/engine/lib/types";
export interface IXrRootProps extends IBaseXmlNode {}
+/**
+ * todo;
+ */
export function XrRoot(props: IXrRootProps): JSXNode {
const { width, height, x, y } = normalizeBaseNodeProps(props);
diff --git a/src/engine/forms/components/base/XrScrollView.component.tsx b/src/engine/forms/components/base/XrScrollView.component.tsx
index f337b1994..5a759a528 100644
--- a/src/engine/forms/components/base/XrScrollView.component.tsx
+++ b/src/engine/forms/components/base/XrScrollView.component.tsx
@@ -17,6 +17,9 @@ export interface IXrScrollViewProps extends IBaseXmlNode {
scrollProfile?: string;
}
+/**
+ * todo;
+ */
export function XrScrollView(props: IXrScrollViewProps): JSXNode {
const {
tag = "scroll_view",
diff --git a/src/engine/forms/components/base/XrTabButton.component.tsx b/src/engine/forms/components/base/XrTabButton.component.tsx
index 6d897ce43..01073a529 100644
--- a/src/engine/forms/components/base/XrTabButton.component.tsx
+++ b/src/engine/forms/components/base/XrTabButton.component.tsx
@@ -12,6 +12,9 @@ export interface IXrTabButtonProps extends IBaseXmlNode {
stretch?: boolean;
}
+/**
+ * todo;
+ */
export function XrTabButton(props: IXrTabButtonProps): JSXNode {
const { x, y, width, height, children, texture, id, stretch } = normalizeBaseNodeProps(props);
diff --git a/src/engine/forms/demo_play_control.tsx b/src/engine/forms/demo_play_control.tsx
index 4e0bfc3ab..d9f74dd9c 100644
--- a/src/engine/forms/demo_play_control.tsx
+++ b/src/engine/forms/demo_play_control.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/game/GameUi.component.16.tsx b/src/engine/forms/game/GameUi.component.16.tsx
index f562f25f0..be1501da2 100644
--- a/src/engine/forms/game/GameUi.component.16.tsx
+++ b/src/engine/forms/game/GameUi.component.16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function GameUi(): JSXNode {
return (
diff --git a/src/engine/forms/game/GameUi.component.tsx b/src/engine/forms/game/GameUi.component.tsx
index 9498c77ed..b0229bc92 100644
--- a/src/engine/forms/game/GameUi.component.tsx
+++ b/src/engine/forms/game/GameUi.component.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { captions } from "@/engine/lib/constants/captions";
+/**
+ * todo;
+ */
export function GameUi(): JSXNode {
return (
diff --git a/src/engine/forms/game/heli/heli_progress.tsx b/src/engine/forms/game/heli/heli_progress.tsx
index 50edeba03..a2aa9cdc4 100644
--- a/src/engine/forms/game/heli/heli_progress.tsx
+++ b/src/engine/forms/game/heli/heli_progress.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/MapDescription.component.16.tsx b/src/engine/forms/game/map/MapDescription.component.16.tsx
index e8b883294..f4c3696bf 100644
--- a/src/engine/forms/game/map/MapDescription.component.16.tsx
+++ b/src/engine/forms/game/map/MapDescription.component.16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MapDescription(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/MapDescription.component.tsx b/src/engine/forms/game/map/MapDescription.component.tsx
index 662a141f9..ca94c1b48 100644
--- a/src/engine/forms/game/map/MapDescription.component.tsx
+++ b/src/engine/forms/game/map/MapDescription.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MapDescription(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/MapSpots.component.16.tsx b/src/engine/forms/game/map/MapSpots.component.16.tsx
index 9d5f7bc10..1aac8948a 100644
--- a/src/engine/forms/game/map/MapSpots.component.16.tsx
+++ b/src/engine/forms/game/map/MapSpots.component.16.tsx
@@ -6,6 +6,9 @@ import { SmartTerrainSpots } from "@/engine/forms/game/map/spots/SmartTerrainSpo
import { SquadSpots } from "@/engine/forms/game/map/spots/SquadSpots";
import { TaskSpots } from "@/engine/forms/game/map/spots/TaskSpots";
+/**
+ * todo;
+ */
export function MapSpots(): JSXNode {
return (
@@ -349,8 +352,10 @@ export function MapSpots(): JSXNode {
- {/** */}
+ {/**
+
+ */}
ui_inGame2_PDA_icon_secret
@@ -848,7 +853,7 @@ export function MapSpots(): JSXNode {
>
ui_inGame2_PDA_icon_location
- {/** */}
+ {/**
+
+ */}
ui_inGame2_PDA_icon_secret
@@ -848,11 +853,13 @@ export function MapSpots(): JSXNode {
>
ui_inGame2_PDA_icon_location
- {/** */}
+ -->
+ */}
diff --git a/src/engine/forms/game/map/Pda.component.16.tsx b/src/engine/forms/game/map/Pda.component.16.tsx
index 94642994c..fdb0c86dd 100644
--- a/src/engine/forms/game/map/Pda.component.16.tsx
+++ b/src/engine/forms/game/map/Pda.component.16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function Pda(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/Pda.component.tsx b/src/engine/forms/game/map/Pda.component.tsx
index 4854e2ae4..aac3908a4 100644
--- a/src/engine/forms/game/map/Pda.component.tsx
+++ b/src/engine/forms/game/map/Pda.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function Pda(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/spots/MapMultiplayerSpots.tsx b/src/engine/forms/game/map/spots/MapMultiplayerSpots.tsx
index 34fc0ee85..e3782bc6b 100644
--- a/src/engine/forms/game/map/spots/MapMultiplayerSpots.tsx
+++ b/src/engine/forms/game/map/spots/MapMultiplayerSpots.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MapMultiplayerSpots(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/spots/MapRelationSpots.tsx b/src/engine/forms/game/map/spots/MapRelationSpots.tsx
index d3df11a44..f5340a024 100644
--- a/src/engine/forms/game/map/spots/MapRelationSpots.tsx
+++ b/src/engine/forms/game/map/spots/MapRelationSpots.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MapRelationSpots(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/spots/SmartTerrainSpots.tsx b/src/engine/forms/game/map/spots/SmartTerrainSpots.tsx
index 0b5127da3..e8c1b4b25 100644
--- a/src/engine/forms/game/map/spots/SmartTerrainSpots.tsx
+++ b/src/engine/forms/game/map/spots/SmartTerrainSpots.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function SmartTerrainSpots(): JSXNode {
return (
diff --git a/src/engine/forms/game/map/spots/SquadSpots.tsx b/src/engine/forms/game/map/spots/SquadSpots.tsx
index 162361537..81bc346ea 100644
--- a/src/engine/forms/game/map/spots/SquadSpots.tsx
+++ b/src/engine/forms/game/map/spots/SquadSpots.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ *
+ */
export function SquadSpots(): JSXNode {
return (
@@ -171,7 +174,7 @@ export function SquadSpots(): JSXNode {
- {/**
- */}
+ */}
@@ -461,13 +464,16 @@ export function TaskSpots(): JSXNode {
- {/** */}
+ -->
+ */}
- {/** */}
+ -->
+ */}
@@ -708,7 +715,8 @@ export function TaskSpots(): JSXNode {
- {/** */}
+ -->
+ */}
);
}
diff --git a/src/engine/forms/game_tutorials.tsx b/src/engine/forms/game_tutorials.tsx
index 19814930f..e11791d05 100644
--- a/src/engine/forms/game_tutorials.tsx
+++ b/src/engine/forms/game_tutorials.tsx
@@ -10,6 +10,9 @@ import {
GameVendorsIntro,
} from "@/engine/forms/tutorials";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/grenade.tsx b/src/engine/forms/grenade.tsx
index b516f8a38..1967b3eb5 100644
--- a/src/engine/forms/grenade.tsx
+++ b/src/engine/forms/grenade.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/hint_item.tsx b/src/engine/forms/hint_item.tsx
index 1f156afa6..971518466 100644
--- a/src/engine/forms/hint_item.tsx
+++ b/src/engine/forms/hint_item.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ingame_msglog_mp.tsx b/src/engine/forms/ingame_msglog_mp.tsx
index f04b4d560..0bca27e43 100644
--- a/src/engine/forms/ingame_msglog_mp.tsx
+++ b/src/engine/forms/ingame_msglog_mp.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ingame_msglog_sp.tsx b/src/engine/forms/ingame_msglog_sp.tsx
index d13c33bc7..207ea1c0a 100644
--- a/src/engine/forms/ingame_msglog_sp.tsx
+++ b/src/engine/forms/ingame_msglog_sp.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/interaction/SleepDialog.component.16.tsx b/src/engine/forms/interaction/SleepDialog.component.16.tsx
index 4a47a8beb..996357bee 100644
--- a/src/engine/forms/interaction/SleepDialog.component.16.tsx
+++ b/src/engine/forms/interaction/SleepDialog.component.16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/interaction/SleepDialog.component.tsx b/src/engine/forms/interaction/SleepDialog.component.tsx
index 204f463ff..dc319b9ec 100644
--- a/src/engine/forms/interaction/SleepDialog.component.tsx
+++ b/src/engine/forms/interaction/SleepDialog.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/inventory_new.tsx b/src/engine/forms/inventory_new.tsx
index fa8426401..e76ed1bb1 100644
--- a/src/engine/forms/inventory_new.tsx
+++ b/src/engine/forms/inventory_new.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/inventory_new_16.tsx b/src/engine/forms/inventory_new_16.tsx
index fa8426401..e76ed1bb1 100644
--- a/src/engine/forms/inventory_new_16.tsx
+++ b/src/engine/forms/inventory_new_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/inventory_upgrade.tsx b/src/engine/forms/inventory_upgrade.tsx
index 31a998650..464b1e7b6 100644
--- a/src/engine/forms/inventory_upgrade.tsx
+++ b/src/engine/forms/inventory_upgrade.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/inventory_upgrade_16.tsx b/src/engine/forms/inventory_upgrade_16.tsx
index 89cad9704..d9d92fdd6 100644
--- a/src/engine/forms/inventory_upgrade_16.tsx
+++ b/src/engine/forms/inventory_upgrade_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/inventory_upgrade_info.tsx b/src/engine/forms/inventory_upgrade_info.tsx
index fa8426401..e76ed1bb1 100644
--- a/src/engine/forms/inventory_upgrade_info.tsx
+++ b/src/engine/forms/inventory_upgrade_info.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/inventory_upgrade_info_16.tsx b/src/engine/forms/inventory_upgrade_info_16.tsx
index fa8426401..e76ed1bb1 100644
--- a/src/engine/forms/inventory_upgrade_info_16.tsx
+++ b/src/engine/forms/inventory_upgrade_info_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/maingame.tsx b/src/engine/forms/maingame.tsx
index 2a6b727e2..ca10bc1ff 100644
--- a/src/engine/forms/maingame.tsx
+++ b/src/engine/forms/maingame.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { GameUi } from "@/engine/forms/game/GameUi.component";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/maingame_16.tsx b/src/engine/forms/maingame_16.tsx
index 62b01d4a5..84e24276c 100644
--- a/src/engine/forms/maingame_16.tsx
+++ b/src/engine/forms/maingame_16.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { GameUi } from "@/engine/forms/game/GameUi.component.16";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/maingame_pda_msg.tsx b/src/engine/forms/maingame_pda_msg.tsx
index eb67157ea..fe94f2402 100644
--- a/src/engine/forms/maingame_pda_msg.tsx
+++ b/src/engine/forms/maingame_pda_msg.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/maingame_pda_msg_16.tsx b/src/engine/forms/maingame_pda_msg_16.tsx
index 2c65b90a7..a4be57051 100644
--- a/src/engine/forms/maingame_pda_msg_16.tsx
+++ b/src/engine/forms/maingame_pda_msg_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/map_desc.tsx b/src/engine/forms/map_desc.tsx
index 6f9b3f526..d686585a0 100644
--- a/src/engine/forms/map_desc.tsx
+++ b/src/engine/forms/map_desc.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { MapDescription } from "@/engine/forms/game/map/MapDescription.component";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/map_desc_16.tsx b/src/engine/forms/map_desc_16.tsx
index da3e20d81..680acbc85 100644
--- a/src/engine/forms/map_desc_16.tsx
+++ b/src/engine/forms/map_desc_16.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { MapDescription } from "@/engine/forms/game/map/MapDescription.component.16";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/map_spots.tsx b/src/engine/forms/map_spots.tsx
index 3662d3bd5..95a25d82e 100644
--- a/src/engine/forms/map_spots.tsx
+++ b/src/engine/forms/map_spots.tsx
@@ -2,6 +2,9 @@
import { MapSpots } from "@/engine/forms/game/map/MapSpots.component";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/map_spots_16.tsx b/src/engine/forms/map_spots_16.tsx
index 113a1558b..49a8b7f42 100644
--- a/src/engine/forms/map_spots_16.tsx
+++ b/src/engine/forms/map_spots_16.tsx
@@ -2,6 +2,9 @@
import { MapSpots } from "@/engine/forms/game/map/MapSpots.component.16";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return ;
}
diff --git a/src/engine/forms/menu/LoadDialog.component.tsx b/src/engine/forms/menu/LoadDialog.component.tsx
index 902ce424b..8b8d6edb8 100644
--- a/src/engine/forms/menu/LoadDialog.component.tsx
+++ b/src/engine/forms/menu/LoadDialog.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/MainMenu.component.tsx b/src/engine/forms/menu/MainMenu.component.tsx
index 235d63a1c..544ee08b7 100644
--- a/src/engine/forms/menu/MainMenu.component.tsx
+++ b/src/engine/forms/menu/MainMenu.component.tsx
@@ -4,6 +4,9 @@ import { captions } from "@/engine/lib/constants/captions/captions";
import { fonts } from "@/engine/lib/constants/fonts";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
@@ -105,6 +108,9 @@ export function create(): JSXNode {
);
}
+/**
+ * todo;
+ */
function MainMenuBackground(): JSXNode {
return (
diff --git a/src/engine/forms/menu/MenuCredits.tsx b/src/engine/forms/menu/MenuCredits.tsx
index c2d1cf0e2..5d4f615db 100644
--- a/src/engine/forms/menu/MenuCredits.tsx
+++ b/src/engine/forms/menu/MenuCredits.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MenuCredits(): JSXNode {
return (
diff --git a/src/engine/forms/menu/OptionsDialog.component.tsx b/src/engine/forms/menu/OptionsDialog.component.tsx
index cdcda72d3..497dcd76d 100644
--- a/src/engine/forms/menu/OptionsDialog.component.tsx
+++ b/src/engine/forms/menu/OptionsDialog.component.tsx
@@ -6,6 +6,9 @@ import { OptionsSounds } from "@/engine/forms/menu/options/OptionsSounds.part";
import { OptionsVideo } from "@/engine/forms/menu/options/OptionsVideo.part";
import { OptionsVideoAdvanced } from "@/engine/forms/menu/options/OptionsVideoAdvanced.part";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
@@ -30,6 +33,9 @@ export function create(): JSXNode {
);
}
+/**
+ * todo;
+ */
function OptionsBody(): JSXNode {
return (
@@ -105,6 +111,9 @@ function OptionsBody(): JSXNode {
);
}
+/**
+ * todo;
+ */
function OptionsBackground(): JSXNode {
return (
@@ -126,6 +135,9 @@ function OptionsBackground(): JSXNode {
);
}
+/**
+ *
+ */
function OptionsPatchDownload(): JSXNode {
return (
diff --git a/src/engine/forms/menu/SaveDialog.component.tsx b/src/engine/forms/menu/SaveDialog.component.tsx
index e7af637f4..9fceff10f 100644
--- a/src/engine/forms/menu/SaveDialog.component.tsx
+++ b/src/engine/forms/menu/SaveDialog.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugCommandsSection.component.tsx b/src/engine/forms/menu/debug/DebugCommandsSection.component.tsx
index 4642aa8b4..24f0b3816 100644
--- a/src/engine/forms/menu/debug/DebugCommandsSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugCommandsSection.component.tsx
@@ -4,6 +4,9 @@ import { XrCheckBox, XrComponent, XrRoot, XrText } from "@/engine/forms/componen
import { XrScrollView } from "@/engine/forms/components/base/XrScrollView.component";
import { SECTION_HEIGHT, SECTION_WIDTH } from "@/engine/forms/menu/debug/DebugDialog.component";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugDialog.component.tsx b/src/engine/forms/menu/debug/DebugDialog.component.tsx
index 65cea106b..bbf628d47 100644
--- a/src/engine/forms/menu/debug/DebugDialog.component.tsx
+++ b/src/engine/forms/menu/debug/DebugDialog.component.tsx
@@ -19,6 +19,9 @@ export const SECTION_HEIGHT: number = BASE_HEIGHT - 16;
const TEXT_COLOR_DARKER: IRgbColor = { r: 170, g: 170, b: 170 };
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugGeneralSection.component.tsx b/src/engine/forms/menu/debug/DebugGeneralSection.component.tsx
index 680a6a5d8..61fe5d38f 100644
--- a/src/engine/forms/menu/debug/DebugGeneralSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugGeneralSection.component.tsx
@@ -9,6 +9,9 @@ import { textures } from "@/engine/lib/constants/textures";
const BASE_WIDTH: number = SECTION_WIDTH;
const BASE_HEIGHT: number = SECTION_HEIGHT;
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugItemsSection.component.tsx b/src/engine/forms/menu/debug/DebugItemsSection.component.tsx
index c8facd963..29d518b3d 100644
--- a/src/engine/forms/menu/debug/DebugItemsSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugItemsSection.component.tsx
@@ -7,6 +7,9 @@ import { SECTION_HEIGHT, SECTION_WIDTH } from "@/engine/forms/menu/debug/DebugDi
import { WHITE } from "@/engine/lib/constants/colors";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugObjectSection.component.tsx b/src/engine/forms/menu/debug/DebugObjectSection.component.tsx
index 06ffc3541..27c4a5177 100644
--- a/src/engine/forms/menu/debug/DebugObjectSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugObjectSection.component.tsx
@@ -4,6 +4,9 @@ import { Xr3tButton, XrCheckBox, XrRoot, XrStatic, XrText } from "@/engine/forms
import { WHITE } from "@/engine/lib/constants/colors";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
@@ -24,6 +27,9 @@ export function create(): JSXNode {
);
}
+/**
+ * todo;
+ */
function renderLoggingButtons(): JSXNode {
return (
@@ -85,6 +91,9 @@ function renderLoggingButtons(): JSXNode {
);
}
+/**
+ * todo;
+ */
function renderRelationButtons(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugPlayerSection.component.tsx b/src/engine/forms/menu/debug/DebugPlayerSection.component.tsx
index 9ff7810b3..c93426ce5 100644
--- a/src/engine/forms/menu/debug/DebugPlayerSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugPlayerSection.component.tsx
@@ -6,6 +6,9 @@ import { textures } from "@/engine/lib/constants/textures";
const BASE_WIDTH: number = SECTION_WIDTH;
const BASE_HEIGHT: number = SECTION_HEIGHT;
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugPositionSection.component.tsx b/src/engine/forms/menu/debug/DebugPositionSection.component.tsx
index 9ff7810b3..c93426ce5 100644
--- a/src/engine/forms/menu/debug/DebugPositionSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugPositionSection.component.tsx
@@ -6,6 +6,9 @@ import { textures } from "@/engine/lib/constants/textures";
const BASE_WIDTH: number = SECTION_WIDTH;
const BASE_HEIGHT: number = SECTION_HEIGHT;
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugRegistrySection.component.tsx b/src/engine/forms/menu/debug/DebugRegistrySection.component.tsx
index 7e679b62c..e66ebe164 100644
--- a/src/engine/forms/menu/debug/DebugRegistrySection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugRegistrySection.component.tsx
@@ -4,6 +4,9 @@ import { Xr3tButton } from "@/engine/forms/components/base";
import { WHITE } from "@/engine/lib/constants/colors";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugSoundSection.component.tsx b/src/engine/forms/menu/debug/DebugSoundSection.component.tsx
index 9ff7810b3..c93426ce5 100644
--- a/src/engine/forms/menu/debug/DebugSoundSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugSoundSection.component.tsx
@@ -6,6 +6,9 @@ import { textures } from "@/engine/lib/constants/textures";
const BASE_WIDTH: number = SECTION_WIDTH;
const BASE_HEIGHT: number = SECTION_HEIGHT;
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugSpawnSection.component.tsx b/src/engine/forms/menu/debug/DebugSpawnSection.component.tsx
index b99c4f026..74b2209c6 100644
--- a/src/engine/forms/menu/debug/DebugSpawnSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugSpawnSection.component.tsx
@@ -7,6 +7,9 @@ import { SECTION_HEIGHT, SECTION_WIDTH } from "@/engine/forms/menu/debug/DebugDi
import { WHITE } from "@/engine/lib/constants/colors";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugTeleportSection.component.tsx b/src/engine/forms/menu/debug/DebugTeleportSection.component.tsx
index f8076555a..a482666dd 100644
--- a/src/engine/forms/menu/debug/DebugTeleportSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugTeleportSection.component.tsx
@@ -7,6 +7,9 @@ import { SECTION_HEIGHT, SECTION_WIDTH } from "@/engine/forms/menu/debug/DebugDi
import { WHITE } from "@/engine/lib/constants/colors";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/debug/DebugUiSection.component.tsx b/src/engine/forms/menu/debug/DebugUiSection.component.tsx
index 6ae0050ea..1b873f1a9 100644
--- a/src/engine/forms/menu/debug/DebugUiSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugUiSection.component.tsx
@@ -10,6 +10,9 @@ import { IRgbColor } from "@/engine/lib/types";
const BASE_WIDTH: number = SECTION_WIDTH;
const BASE_HEIGHT: number = SECTION_HEIGHT;
+/**
+ * todo;
+ */
export function create(): JSXNode {
const DEFAULT_SPACING: number = 12;
diff --git a/src/engine/forms/menu/debug/DebugWeatherSection.component.tsx b/src/engine/forms/menu/debug/DebugWeatherSection.component.tsx
index 06a0f4299..f21fd47fe 100644
--- a/src/engine/forms/menu/debug/DebugWeatherSection.component.tsx
+++ b/src/engine/forms/menu/debug/DebugWeatherSection.component.tsx
@@ -7,6 +7,9 @@ import { WHITE } from "@/engine/lib/constants/colors";
import { fonts } from "@/engine/lib/constants/fonts";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerAwards.component.tsx b/src/engine/forms/menu/multiplayer/MultiplayerAwards.component.tsx
index 0e24c9395..115202390 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerAwards.component.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerAwards.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.16.tsx b/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.16.tsx
index 6333317a4..eec9795e4 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.16.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.16.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MultiplayerBuyButtons16(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.tsx b/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.tsx
index d2cd88c02..988980d79 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerBuyButtons.tsx
@@ -1,5 +1,8 @@
import { Fragment, JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function MultiplayerBuyButtons(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerGamespy.component.tsx b/src/engine/forms/menu/multiplayer/MultiplayerGamespy.component.tsx
index 8592ae636..32bb92618 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerGamespy.component.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerGamespy.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerLocalnet.component.tsx b/src/engine/forms/menu/multiplayer/MultiplayerLocalnet.component.tsx
index 9943d433a..fc77914a4 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerLocalnet.component.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerLocalnet.component.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/menu/multiplayer/MultiplayerOffline.component.tsx b/src/engine/forms/menu/multiplayer/MultiplayerOffline.component.tsx
index f4a5cc661..5193fbef0 100644
--- a/src/engine/forms/menu/multiplayer/MultiplayerOffline.component.tsx
+++ b/src/engine/forms/menu/multiplayer/MultiplayerOffline.component.tsx
@@ -5,6 +5,9 @@ import { MultiplayerTabDemo } from "@/engine/forms/menu/multiplayer/tabs/Multipl
import { MultiplayerTabOptions } from "@/engine/forms/menu/multiplayer/tabs/MultiplayerTabOptions.part";
import { MultiplayerTabServer } from "@/engine/forms/menu/multiplayer/tabs/MultiplayerTabServer.part";
+/**
+ *
+ */
export function create(): JSXNode {
return (
@@ -138,7 +141,7 @@ export function create(): JSXNode {
- {/**
+ {/*
* -->
+
+/**
+ * todo;
+ */
export function create(): JSXNode {
- /**
+ /*
*
* <_rank_caption x="23" y="150" width="153" height="15">
*
diff --git a/src/engine/forms/tutorials/GameVendorsIntro.component.tsx b/src/engine/forms/tutorials/GameVendorsIntro.component.tsx
index 91e32e3cc..3731493c1 100644
--- a/src/engine/forms/tutorials/GameVendorsIntro.component.tsx
+++ b/src/engine/forms/tutorials/GameVendorsIntro.component.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { gameConfig } from "@/engine/lib/configs/GameConfig";
+/**
+ * todo;
+ */
export function GameVendorsIntro(): JSXNode {
if (gameConfig.UI.ARE_INTRO_VIDEOS_ENABLED) {
return (
diff --git a/src/engine/forms/ui_credits.tsx b/src/engine/forms/ui_credits.tsx
index 155bcfd3f..d69206b40 100644
--- a/src/engine/forms/ui_credits.tsx
+++ b/src/engine/forms/ui_credits.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { MenuCredits } from "@/engine/forms/menu/MenuCredits";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_credits_16.tsx b/src/engine/forms/ui_credits_16.tsx
index 80e342487..c2c7e446c 100644
--- a/src/engine/forms/ui_credits_16.tsx
+++ b/src/engine/forms/ui_credits_16.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { MenuCredits } from "@/engine/forms/menu/MenuCredits";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_custom_msgs.tsx b/src/engine/forms/ui_custom_msgs.tsx
index 605877602..24fa53c24 100644
--- a/src/engine/forms/ui_custom_msgs.tsx
+++ b/src/engine/forms/ui_custom_msgs.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_detector_artefact.tsx b/src/engine/forms/ui_detector_artefact.tsx
index 2a79096f6..2f6267c28 100644
--- a/src/engine/forms/ui_detector_artefact.tsx
+++ b/src/engine/forms/ui_detector_artefact.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_ahunt.tsx b/src/engine/forms/ui_game_ahunt.tsx
index a6b1eeac4..5bb0f4575 100644
--- a/src/engine/forms/ui_game_ahunt.tsx
+++ b/src/engine/forms/ui_game_ahunt.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_ahunt_16.tsx b/src/engine/forms/ui_game_ahunt_16.tsx
index f8b3cc7ef..707204da2 100644
--- a/src/engine/forms/ui_game_ahunt_16.tsx
+++ b/src/engine/forms/ui_game_ahunt_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_cta.tsx b/src/engine/forms/ui_game_cta.tsx
index a6b1eeac4..5bb0f4575 100644
--- a/src/engine/forms/ui_game_cta.tsx
+++ b/src/engine/forms/ui_game_cta.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_cta_16.tsx b/src/engine/forms/ui_game_cta_16.tsx
index f8b3cc7ef..707204da2 100644
--- a/src/engine/forms/ui_game_cta_16.tsx
+++ b/src/engine/forms/ui_game_cta_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_dm.tsx b/src/engine/forms/ui_game_dm.tsx
index 6390599ca..399ba3b40 100644
--- a/src/engine/forms/ui_game_dm.tsx
+++ b/src/engine/forms/ui_game_dm.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_dm_16.tsx b/src/engine/forms/ui_game_dm_16.tsx
index ddc3d1369..311678268 100644
--- a/src/engine/forms/ui_game_dm_16.tsx
+++ b/src/engine/forms/ui_game_dm_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_over.tsx b/src/engine/forms/ui_game_over.tsx
index 667102e62..193426d3c 100644
--- a/src/engine/forms/ui_game_over.tsx
+++ b/src/engine/forms/ui_game_over.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_tdm.tsx b/src/engine/forms/ui_game_tdm.tsx
index 996539c60..b87b201d9 100644
--- a/src/engine/forms/ui_game_tdm.tsx
+++ b/src/engine/forms/ui_game_tdm.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_game_tdm_16.tsx b/src/engine/forms/ui_game_tdm_16.tsx
index a89c78571..8f61b38ee 100644
--- a/src/engine/forms/ui_game_tdm_16.tsx
+++ b/src/engine/forms/ui_game_tdm_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_keybinding.tsx b/src/engine/forms/ui_keybinding.tsx
index b2e067533..f2efab169 100644
--- a/src/engine/forms/ui_keybinding.tsx
+++ b/src/engine/forms/ui_keybinding.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_keybinding_gamepad.tsx b/src/engine/forms/ui_keybinding_gamepad.tsx
index 88f35c3b2..31bade789 100644
--- a/src/engine/forms/ui_keybinding_gamepad.tsx
+++ b/src/engine/forms/ui_keybinding_gamepad.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_mapinfo.tsx b/src/engine/forms/ui_mapinfo.tsx
index f84be6925..a82bb610d 100644
--- a/src/engine/forms/ui_mapinfo.tsx
+++ b/src/engine/forms/ui_mapinfo.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_mm_loading_screen.tsx b/src/engine/forms/ui_mm_loading_screen.tsx
index f3b60f210..60da6f98f 100644
--- a/src/engine/forms/ui_mm_loading_screen.tsx
+++ b/src/engine/forms/ui_mm_loading_screen.tsx
@@ -2,6 +2,9 @@ import { JSXNode, JSXXML } from "jsx-xml";
import { textures } from "@/engine/lib/constants/textures";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_mm_loading_screen_16.tsx b/src/engine/forms/ui_mm_loading_screen_16.tsx
index 5f11f14ec..015a093d2 100644
--- a/src/engine/forms/ui_mm_loading_screen_16.tsx
+++ b/src/engine/forms/ui_mm_loading_screen_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_mm_versions_dlg.tsx b/src/engine/forms/ui_mm_versions_dlg.tsx
index d36da1559..82563c99d 100644
--- a/src/engine/forms/ui_mm_versions_dlg.tsx
+++ b/src/engine/forms/ui_mm_versions_dlg.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_mm_versions_dlg_16.tsx b/src/engine/forms/ui_mm_versions_dlg_16.tsx
index c09ff5be0..4d2759bad 100644
--- a/src/engine/forms/ui_mm_versions_dlg_16.tsx
+++ b/src/engine/forms/ui_mm_versions_dlg_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_numpad_wnd.tsx b/src/engine/forms/ui_numpad_wnd.tsx
index cf20316c9..46e3f9802 100644
--- a/src/engine/forms/ui_numpad_wnd.tsx
+++ b/src/engine/forms/ui_numpad_wnd.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_spawn_dlg.tsx b/src/engine/forms/ui_spawn_dlg.tsx
index 55aba6787..90bbd9106 100644
--- a/src/engine/forms/ui_spawn_dlg.tsx
+++ b/src/engine/forms/ui_spawn_dlg.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_ahunt.tsx b/src/engine/forms/ui_team_panels_ahunt.tsx
index 1152ac263..f55dab304 100644
--- a/src/engine/forms/ui_team_panels_ahunt.tsx
+++ b/src/engine/forms/ui_team_panels_ahunt.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_ahunt_16.tsx b/src/engine/forms/ui_team_panels_ahunt_16.tsx
index 26119790e..a292046a1 100644
--- a/src/engine/forms/ui_team_panels_ahunt_16.tsx
+++ b/src/engine/forms/ui_team_panels_ahunt_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_cta.tsx b/src/engine/forms/ui_team_panels_cta.tsx
index 1152ac263..f55dab304 100644
--- a/src/engine/forms/ui_team_panels_cta.tsx
+++ b/src/engine/forms/ui_team_panels_cta.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_cta_16.tsx b/src/engine/forms/ui_team_panels_cta_16.tsx
index 26119790e..a292046a1 100644
--- a/src/engine/forms/ui_team_panels_cta_16.tsx
+++ b/src/engine/forms/ui_team_panels_cta_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_dm.tsx b/src/engine/forms/ui_team_panels_dm.tsx
index 0e559aef2..315c8d025 100644
--- a/src/engine/forms/ui_team_panels_dm.tsx
+++ b/src/engine/forms/ui_team_panels_dm.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_dm_16.tsx b/src/engine/forms/ui_team_panels_dm_16.tsx
index 012d9aa50..a40799c82 100644
--- a/src/engine/forms/ui_team_panels_dm_16.tsx
+++ b/src/engine/forms/ui_team_panels_dm_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_tdm.tsx b/src/engine/forms/ui_team_panels_tdm.tsx
index b9876a8fb..aab688635 100644
--- a/src/engine/forms/ui_team_panels_tdm.tsx
+++ b/src/engine/forms/ui_team_panels_tdm.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/ui_team_panels_tdm_16.tsx b/src/engine/forms/ui_team_panels_tdm_16.tsx
index d48b664c5..3303fd170 100644
--- a/src/engine/forms/ui_team_panels_tdm_16.tsx
+++ b/src/engine/forms/ui_team_panels_tdm_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/video_templ.tsx b/src/engine/forms/video_templ.tsx
index a2212118d..475d34312 100644
--- a/src/engine/forms/video_templ.tsx
+++ b/src/engine/forms/video_templ.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/voting_category.tsx b/src/engine/forms/voting_category.tsx
index aae3b3d80..36f32df60 100644
--- a/src/engine/forms/voting_category.tsx
+++ b/src/engine/forms/voting_category.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/voting_category_16.tsx b/src/engine/forms/voting_category_16.tsx
index 14069d454..63d06ff62 100644
--- a/src/engine/forms/voting_category_16.tsx
+++ b/src/engine/forms/voting_category_16.tsx
@@ -1,5 +1,8 @@
import { JSXNode, JSXXML } from "jsx-xml";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/zone_map.tsx b/src/engine/forms/zone_map.tsx
index 61e7bc21d..b96d004e1 100644
--- a/src/engine/forms/zone_map.tsx
+++ b/src/engine/forms/zone_map.tsx
@@ -4,6 +4,9 @@ import { XrText } from "@/engine/forms/components/base";
import { XrTexture } from "@/engine/forms/components/base/XrTexture.component";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/forms/zone_map_16.tsx b/src/engine/forms/zone_map_16.tsx
index 6eac346eb..24b0af190 100644
--- a/src/engine/forms/zone_map_16.tsx
+++ b/src/engine/forms/zone_map_16.tsx
@@ -4,6 +4,9 @@ import { XrText } from "@/engine/forms/components/base";
import { XrTexture } from "@/engine/forms/components/base/XrTexture.component";
import { fonts } from "@/engine/lib/constants/fonts";
+/**
+ * todo;
+ */
export function create(): JSXNode {
return (
diff --git a/src/engine/lib/configs/GameConfig.ts b/src/engine/lib/configs/GameConfig.ts
index 743b6d169..529410b9c 100644
--- a/src/engine/lib/configs/GameConfig.ts
+++ b/src/engine/lib/configs/GameConfig.ts
@@ -46,6 +46,10 @@ export const gameConfig = {
* Game save file extension by default.
*/
GAME_SAVE_EXTENSION: ".scop",
+ /**
+ * Game save file extension for dynamic data.
+ */
+ GAME_SAVE_DYNAMIC_EXTENSION: ".scopx",
/**
* Game save preview file extension by default.
*/
diff --git a/src/engine/scripts/declarations/callbacks/game.ts b/src/engine/scripts/declarations/callbacks/game.ts
index 848664ccb..86e3cb6e9 100644
--- a/src/engine/scripts/declarations/callbacks/game.ts
+++ b/src/engine/scripts/declarations/callbacks/game.ts
@@ -1,12 +1,13 @@
/**
* Outro conditions for game ending based on alife information.
*/
+import { SaveManager } from "@/engine/core/managers/base/SaveManager";
import { TradeManager } from "@/engine/core/managers/interaction/TradeManager";
import { smartCoversList } from "@/engine/core/objects/server/smart_cover/smart_covers_list";
import { GameOutroManager } from "@/engine/core/ui/game/GameOutroManager";
import { extern } from "@/engine/core/utils/binding";
import { LuaLogger } from "@/engine/core/utils/logging";
-import { TNumberId } from "@/engine/lib/types";
+import { TName, TNumberId } from "@/engine/lib/types";
const logger: LuaLogger = new LuaLogger($filename);
@@ -35,3 +36,23 @@ extern("trade_manager", {
get_sell_discount: (objectId: TNumberId) => TradeManager.getInstance().getSellDiscountForObject(objectId),
get_buy_discount: (objectId: TNumberId) => TradeManager.getInstance().getBuyDiscountForObject(objectId),
});
+
+/**
+ * Called from game engine just before creating game save.
+ */
+extern("on_before_game_save", (saveName: TName) => SaveManager.getInstance().onBeforeGameSave(saveName));
+
+/**
+ * Called from game engine when game save is created.
+ */
+extern("on_game_save", (saveName: TName) => SaveManager.getInstance().onGameSave(saveName));
+
+/**
+ * Called from game engine just before loading game save.
+ */
+extern("on_before_game_load", (saveName: TName) => SaveManager.getInstance().onBeforeGameLoad(saveName));
+
+/**
+ * Called from game engine after loading game save.
+ */
+extern("on_game_load", (saveName: TName) => SaveManager.getInstance().onGameLoad(saveName));
diff --git a/src/engine/scripts/declarations/conditions/world.ts b/src/engine/scripts/declarations/conditions/world.ts
index 42043fdb8..4108bcdf6 100644
--- a/src/engine/scripts/declarations/conditions/world.ts
+++ b/src/engine/scripts/declarations/conditions/world.ts
@@ -8,68 +8,70 @@ import { ESmartTerrainStatus } from "@/engine/core/objects/server/smart_terrain/
import { abort } from "@/engine/core/utils/assertion";
import { extern } from "@/engine/core/utils/binding";
import { anomalyHasArtefact } from "@/engine/core/utils/object/object_anomaly";
-import { ClientObject, LuaArray, Optional, TName } from "@/engine/lib/types";
+import { ClientObject, Optional, TName, TSection, TTimestamp } from "@/engine/lib/types";
/**
- * todo;
+ * @returns whether it is rainy in the game right now
*/
extern("xr_conditions.is_rain", (): boolean => {
return registry.actor !== null && level.rain_factor() > 0;
});
/**
- * todo;
+ * @returns whether it is heavy rain weather in the game right now
*/
extern("xr_conditions.is_heavy_rain", (): boolean => {
return registry.actor !== null && level.rain_factor() >= 0.5;
});
/**
- * todo;
+ * @returns whether it is dark daytime in the game
*/
extern("xr_conditions.is_day", (): boolean => {
- return registry.actor !== null && level.get_time_hours() >= 6 && level.get_time_hours() < 21;
+ const timeHours: TTimestamp = level.get_time_hours();
+
+ return registry.actor !== null && timeHours >= 6 && timeHours < 21;
});
/**
- * todo;
+ * @returns whether it is dark nighttime in the game
*/
extern("xr_conditions.is_dark_night", (): boolean => {
- return registry.actor !== null && (level.get_time_hours() < 3 || level.get_time_hours() > 22);
+ const timeHours: TTimestamp = level.get_time_hours();
+
+ return registry.actor !== null && (timeHours < 3 || timeHours > 22);
});
/**
- * todo;
+ * Check whether anomaly with name has artefact.
+ *
+ * @param anomalyName - name of the anomaly to check
+ * @param artefactSection - section of the artefact to check
+ * @returns whether anomaly has artefact
*/
extern(
"xr_conditions.anomaly_has_artefact",
- (
- actor: ClientObject,
- object: ClientObject,
- [anomalyName, artefactName]: [TName, TName]
- ): LuaMultiReturn<[boolean, Optional>]> => {
- const [hasArtefact, details] = anomalyHasArtefact(actor, object, anomalyName, artefactName);
-
- return $multi(hasArtefact, details);
+ (actor: ClientObject, object: ClientObject, [anomalyName, artefactSection]: [TName, TSection]): boolean => {
+ return anomalyHasArtefact(anomalyName, artefactSection);
}
);
/**
- * todo;
+ * @returns whether surge is completed
*/
extern("xr_conditions.surge_complete", (): boolean => {
return SurgeManager.getInstance().isFinished;
});
/**
- * todo;
+ * @returns whether surge is started
*/
extern("xr_conditions.surge_started", (): boolean => {
return SurgeManager.getInstance().isStarted;
});
/**
- * todo;
+ * @returns whether surge is killing all not hided objects
*/
extern("xr_conditions.surge_kill_all", (): boolean => {
return SurgeManager.getInstance().isKillingAll();
@@ -119,19 +121,22 @@ const ALARM_STATUSES = {
*/
extern(
"xr_conditions.check_smart_alarm_status",
- (actor: ClientObject, npc: ClientObject, params: [TName, string]): boolean => {
- const smartName: TName = params[0];
- const status: ESmartTerrainStatus = ALARM_STATUSES[params[1] as keyof typeof ALARM_STATUSES];
+ (
+ actor: ClientObject,
+ object: ClientObject,
+ [smartName, smartStatus]: [TName, keyof typeof ALARM_STATUSES]
+ ): boolean => {
+ const status: Optional = ALARM_STATUSES[smartStatus];
- if (status === null) {
- abort("Wrong status[%s] in 'check_smart_alarm_status'", tostring(params[1]));
+ if (!status) {
+ abort("Wrong status[%s] in 'check_smart_alarm_status'", status);
}
const smart: SmartTerrain = SimulationBoardManager.getInstance().getSmartTerrainByName(smartName)!;
const smartControl: Optional = smart.smartTerrainActorControl;
if (smartControl === null) {
- abort("Cannot calculate 'check_smart_alarm_status' for smart %s", tostring(smartName));
+ abort("Cannot calculate 'check_smart_alarm_status' for smart '%s'.", tostring(smartName));
}
return smartControl.getSmartTerrainStatus() === status;
diff --git a/src/fixtures/engine/mockEngineGlobals.ts b/src/fixtures/engine/mockEngineGlobals.ts
index e28f22887..3d020f407 100644
--- a/src/fixtures/engine/mockEngineGlobals.ts
+++ b/src/fixtures/engine/mockEngineGlobals.ts
@@ -1,7 +1,9 @@
import { jest } from "@jest/globals";
+import { mockLfs } from "@/fixtures/engine/mocks/lfs.mock";
import { MockLuaLogger } from "@/fixtures/engine/mocks/LuaLogger.mock";
-import { mockTableUtils } from "@/fixtures/engine/mocks/table.mocks";
+import { mockMarshal } from "@/fixtures/engine/mocks/marshal.mock";
+import { mockTableUtils } from "@/fixtures/engine/mocks/table.mock";
/**
* todo;
@@ -12,4 +14,10 @@ export function mockEngineGlobals(): void {
}));
jest.mock("@/engine/core/utils/table", () => mockTableUtils);
+
+ // @ts-ignore
+ global.marshal = mockMarshal;
+
+ // @ts-ignore
+ global.lfs = mockLfs;
}
diff --git a/src/fixtures/engine/mocks/index.ts b/src/fixtures/engine/mocks/index.ts
index 46e9c208d..74a0ac2ba 100644
--- a/src/fixtures/engine/mocks/index.ts
+++ b/src/fixtures/engine/mocks/index.ts
@@ -1,4 +1,3 @@
-export * from "@/fixtures/engine/mocks/registry.mocks";
-export * from "@/fixtures/engine/mocks/scheme.mocks";
-export * from "@/fixtures/engine/mocks/scheme.mocks";
-export * from "@/fixtures/engine/mocks/squads.mocks";
+export * from "@/fixtures/engine/mocks/registry.mock";
+export * from "@/fixtures/engine/mocks/scheme.mock";
+export * from "@/fixtures/engine/mocks/squads.mock";
diff --git a/src/fixtures/engine/mocks/lfs.mock.ts b/src/fixtures/engine/mocks/lfs.mock.ts
new file mode 100644
index 000000000..bf08f2bfc
--- /dev/null
+++ b/src/fixtures/engine/mocks/lfs.mock.ts
@@ -0,0 +1,5 @@
+import { jest } from "@jest/globals";
+
+export const mockLfs = {
+ mkdir: jest.fn(),
+};
diff --git a/src/fixtures/engine/mocks/marshal.mock.ts b/src/fixtures/engine/mocks/marshal.mock.ts
new file mode 100644
index 000000000..b55c8835e
--- /dev/null
+++ b/src/fixtures/engine/mocks/marshal.mock.ts
@@ -0,0 +1,6 @@
+import { jest } from "@jest/globals";
+
+export const mockMarshal = {
+ encode: jest.fn((data) => JSON.stringify(data)),
+ decode: jest.fn((data: string) => JSON.parse(data)),
+};
diff --git a/src/fixtures/engine/mocks/registry.mocks.ts b/src/fixtures/engine/mocks/registry.mock.ts
similarity index 100%
rename from src/fixtures/engine/mocks/registry.mocks.ts
rename to src/fixtures/engine/mocks/registry.mock.ts
diff --git a/src/fixtures/engine/mocks/scheme.mocks.ts b/src/fixtures/engine/mocks/scheme.mock.ts
similarity index 100%
rename from src/fixtures/engine/mocks/scheme.mocks.ts
rename to src/fixtures/engine/mocks/scheme.mock.ts
diff --git a/src/fixtures/engine/mocks/squads.mocks.ts b/src/fixtures/engine/mocks/squads.mock.ts
similarity index 100%
rename from src/fixtures/engine/mocks/squads.mocks.ts
rename to src/fixtures/engine/mocks/squads.mock.ts
diff --git a/src/fixtures/engine/mocks/table.mocks.ts b/src/fixtures/engine/mocks/table.mock.ts
similarity index 100%
rename from src/fixtures/engine/mocks/table.mocks.ts
rename to src/fixtures/engine/mocks/table.mock.ts
diff --git a/src/fixtures/lua/mocks/index.ts b/src/fixtures/lua/mocks/index.ts
index 55ea3c0ba..293cb83e9 100644
--- a/src/fixtures/lua/mocks/index.ts
+++ b/src/fixtures/lua/mocks/index.ts
@@ -1 +1,2 @@
export * from "@/fixtures/lua/mocks/lua_utils";
+export * from "@/fixtures/lua/mocks/lua_io.mock";
diff --git a/src/fixtures/lua/mocks/lua_globals.mocks.ts b/src/fixtures/lua/mocks/lua_globals.mocks.ts
index 360b2370f..e0f915a86 100644
--- a/src/fixtures/lua/mocks/lua_globals.mocks.ts
+++ b/src/fixtures/lua/mocks/lua_globals.mocks.ts
@@ -2,6 +2,7 @@ import { ILuaState, lauxlib, lua, lualib, to_jsstring, to_luastring } from "feng
import { AnyArgs } from "@/engine/lib/types";
import { mockDebug } from "@/fixtures/lua/mocks/lua_debug.mock";
+import { mockIo } from "@/fixtures/lua/mocks/lua_io.mock";
import { mockMath } from "@/fixtures/lua/mocks/lua_math.mocks";
import { mockPairs } from "@/fixtures/lua/mocks/lua_pairs.mock";
import { mockString } from "@/fixtures/lua/mocks/lua_string.mock";
@@ -10,6 +11,9 @@ import { mockToString } from "@/fixtures/lua/mocks/lua_tostring.mock";
import { mockType } from "@/fixtures/lua/mocks/lua_type.mock";
import { MockLuaTable } from "@/fixtures/lua/mocks/LuaTable.mock";
+/**
+ * Mock lua globals in node testing environment.
+ */
export function mockLuaGlobals(): void {
// @ts-ignore
global._G = global;
@@ -24,6 +28,8 @@ export function mockLuaGlobals(): void {
global.math = mockMath;
// @ts-ignore
global.debug = mockDebug;
+ // @ts-ignore
+ global.io = mockIo;
// @ts-ignore
global.$range = (start: number, end: number) => {
diff --git a/src/fixtures/lua/mocks/lua_io.mock.ts b/src/fixtures/lua/mocks/lua_io.mock.ts
new file mode 100644
index 000000000..0c716d1cc
--- /dev/null
+++ b/src/fixtures/lua/mocks/lua_io.mock.ts
@@ -0,0 +1,54 @@
+import { jest } from "@jest/globals";
+
+import { Optional } from "@/engine/lib/types";
+
+/**
+ * Mock generic io file.
+ */
+export class MockIoFile {
+ public static mock(path: string, mode: string, isOpen: boolean = true): LuaFile {
+ return new MockIoFile(path, mode, isOpen) as unknown as LuaFile;
+ }
+
+ public path: string;
+ public mode: string;
+ public isOpen: boolean;
+ public content: Optional = "";
+
+ public constructor(path: string, mode: string, isOpen: boolean = true) {
+ this.path = path;
+ this.mode = mode;
+ this.isOpen = isOpen;
+ }
+
+ public write = jest.fn((data: string): void => {
+ if (!this.isOpen) {
+ throw new Error("Cannot write in closed file.");
+ }
+
+ this.content = data;
+ });
+
+ public close = jest.fn((): void => {
+ this.isOpen = false;
+ });
+
+ public read = jest.fn((): Optional => {
+ return this.content;
+ });
+
+ public asMock = jest.fn((): LuaFile => {
+ return this as unknown as LuaFile;
+ });
+}
+
+export const mockIo = {
+ open: jest.fn((path: string, mode: string) => [new MockIoFile(path, mode)]),
+ type: jest.fn((target) => {
+ if (target instanceof MockIoFile) {
+ return target.isOpen ? "file" : "closed file";
+ } else {
+ return null;
+ }
+ }),
+};
diff --git a/src/fixtures/lua/mocks/lua_string.mock.ts b/src/fixtures/lua/mocks/lua_string.mock.ts
index 98008017b..cc108da8a 100644
--- a/src/fixtures/lua/mocks/lua_string.mock.ts
+++ b/src/fixtures/lua/mocks/lua_string.mock.ts
@@ -174,4 +174,5 @@ export const mockString = {
return Number.parseInt(to_jsstring(lauxlib.luaL_tolstring(L, -1)));
},
+ lower: (target: string) => target.toLowerCase(),
};
diff --git a/src/fixtures/xray/mocks/actions/action_base.mock.ts b/src/fixtures/xray/mocks/actions/action_base.mock.ts
index eb66a53fb..f237e2e68 100644
--- a/src/fixtures/xray/mocks/actions/action_base.mock.ts
+++ b/src/fixtures/xray/mocks/actions/action_base.mock.ts
@@ -44,6 +44,9 @@ export class MockActionBase extends MockLuabindClass {
}
}
+/**
+ * Mock action base method.
+ */
export function mockActionBase(object: Optional = null, name: string = "generic"): ActionBase {
return new MockActionBase(object, name) as unknown as ActionBase;
}
diff --git a/src/fixtures/xray/mocks/fs/FileSystem.mock.ts b/src/fixtures/xray/mocks/fs/FileSystem.mock.ts
index 17218a9c5..8e7011d9e 100644
--- a/src/fixtures/xray/mocks/fs/FileSystem.mock.ts
+++ b/src/fixtures/xray/mocks/fs/FileSystem.mock.ts
@@ -1,6 +1,8 @@
+import * as path from "path";
+
import { jest } from "@jest/globals";
-import { AnyObject, Optional } from "@/engine/lib/types";
+import { AnyObject, Optional, TPath } from "@/engine/lib/types";
import { MockFileSystemList } from "@/fixtures/xray/mocks/fs/FileSystemList.mock";
import { FS_MOCKS } from "@/fixtures/xray/mocks/fs/fs.mock";
@@ -47,6 +49,8 @@ export class MockFileSystem {
public file_delete = jest.fn(() => {});
+ public update_path = jest.fn((base: TPath, part: TPath) => path.join(base, part));
+
public exist = jest.fn((root: string, path: string) => {
return Boolean(this.mocks[root] && this.mocks[root][path]);
});
diff --git a/src/fixtures/xray/mocks/objects/client/danger_object.mock.ts b/src/fixtures/xray/mocks/objects/client/danger_object.mock.ts
index 6c87b554e..aeb3b9a9d 100644
--- a/src/fixtures/xray/mocks/objects/client/danger_object.mock.ts
+++ b/src/fixtures/xray/mocks/objects/client/danger_object.mock.ts
@@ -1,3 +1,7 @@
+import { ClientObject, Optional, TDangerType } from "@/engine/lib/types";
+import { mockClientGameObject } from "@/fixtures/xray";
+import { MockVector } from "@/fixtures/xray/mocks/vector.mock";
+
/**
* todo;
*/
@@ -13,4 +17,25 @@ export class MockDangerObject {
public static hit: number = 2;
public static sound: number = 1;
public static visual: number = 0;
+
+ public dangerType: TDangerType = 6;
+ public dangerObject: ClientObject = mockClientGameObject();
+ public dangerDependentObject: Optional = null;
+ public dangerPosition: MockVector = MockVector.create(1.5, -0.5, 1);
+
+ public position(): MockVector {
+ return this.dangerPosition;
+ }
+
+ public object(): ClientObject {
+ return this.dangerObject;
+ }
+
+ public dependent_object(): Optional {
+ return this.dangerDependentObject;
+ }
+
+ public type(): TDangerType {
+ return this.dangerType;
+ }
}
diff --git a/src/fixtures/xray/mocks/objects/client/game_object.mock.ts b/src/fixtures/xray/mocks/objects/client/game_object.mock.ts
index 60fcd137d..5e6d72fe3 100644
--- a/src/fixtures/xray/mocks/objects/client/game_object.mock.ts
+++ b/src/fixtures/xray/mocks/objects/client/game_object.mock.ts
@@ -110,6 +110,7 @@ export function mockClientGameObject({
.filter(Boolean)
.forEach((it) => inRestrictions.push(it));
}),
+ best_danger: rest.best_danger || jest.fn(() => null),
bleeding,
can_select_weapon: rest.can_select_weapon || jest.fn(),
change_team: rest.change_team || jest.fn(),
@@ -118,6 +119,7 @@ export function mockClientGameObject({
clsid,
clear_animations: rest.clear_animations || jest.fn(),
command: rest.command || jest.fn(),
+ critically_wounded: rest.critically_wounded || jest.fn(() => false),
direction: rest.direction || jest.fn(() => objectDirection),
disable_hit_marks: rest.disable_hit_marks || jest.fn(),
disable_info_portion:
diff --git a/src/fixtures/xray/mocks/objects/server/cse_alife_human_stalker.mock.ts b/src/fixtures/xray/mocks/objects/server/cse_alife_human_stalker.mock.ts
index a31a7b3f7..4029fadd2 100644
--- a/src/fixtures/xray/mocks/objects/server/cse_alife_human_stalker.mock.ts
+++ b/src/fixtures/xray/mocks/objects/server/cse_alife_human_stalker.mock.ts
@@ -20,6 +20,6 @@ export function mockServerAlifeHumanStalker(base: Partial = {
...base,
community: base.community || jest.fn(() => "stalker"),
force_set_goodwill: base.force_set_goodwill || jest.fn(),
- o_torso: base.o_torso || jest.fn(() => ({} as unknown as rotation)),
+ o_torso: base.o_torso || jest.fn(() => ({}) as unknown as rotation),
} as unknown as ServerHumanObject) as unknown as ServerHumanObject;
}
diff --git a/src/typedefs/xray16 b/src/typedefs/xray16
index 47d6923c4..7a8856eb0 160000
--- a/src/typedefs/xray16
+++ b/src/typedefs/xray16
@@ -1 +1 @@
-Subproject commit 47d6923c42953d64ed6699f4921dcc43cd8d591c
+Subproject commit 7a8856eb0db35854464009ac2640a7318e9f3173