From 3a73b243d37f7fb30ebc61b4a6db12e8464cd138 Mon Sep 17 00:00:00 2001 From: Borig Date: Sat, 1 Feb 2025 16:26:08 +1300 Subject: [PATCH 1/4] Terraforming --- .github/workflows/build.yml | 5 +- CONTRIBUTING.md | 34 +- README.md | 1 - package-lock.json | 2359 ++--------------- package.json | 18 - src/engine/action/hook/task.ts | 2 - src/engine/action/pipe/item-swap.action.ts | 1 - src/engine/action/pipe/move-item.action.ts | 1 - src/engine/plugins/loader.ts | 1 - src/engine/util/strings.ts | 3 - src/engine/world/instances.ts | 4 - src/engine/world/items/item-container.ts | 3 - src/engine/world/map/chunk-manager.ts | 1 - src/engine/world/map/collision-map.ts | 4 - src/engine/world/position.ts | 1 - src/plugins/items/herblore/clean-herb.ts | 2 - .../helpers/rotten-potato-helpers.ts | 1 - .../rotten-potato/hooks/rotten-potato-eat.ts | 1 - .../rotten-potato/hooks/rotten-potato-peel.ts | 1 - .../items/shopping/sell-to-shop.plugin.ts | 1 - src/plugins/objects/crates/crates.plugin.ts | 1 - src/plugins/player/follow-player.plugin.js | 1 - src/plugins/skills/firemaking/data.ts | 8 - 23 files changed, 184 insertions(+), 2270 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71c04ad44..b485b6fbf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Lint & Build Project +name: Build Project on: pull_request: @@ -22,9 +22,6 @@ jobs: - name: Install Node Modules run: npm i - - name: Run Linter - run: npm run lint - - name: Run Typecheck run: npm run typecheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f5cae3e9..f8c3e5b53 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,35 +6,9 @@ RuneJS was created with the intention of utilizing JavaScript/TypeScript and Nod - This defeats the purpose of RuneJS by implementing basic flows that any regular Java-based server would use. Think outside the box and really utilize ES6, TypeScript, Node, and RxJS! :) 2. Additional/outside dependencies - Sometimes additional dependencies cannot be avoided, but we'd like to avoid them as much as possible. RuneJS intends to be simple and easy for anyone to pick up, without requiring the user to set up any databases or additional third party systems. - - In some cases this is of course unavoidable, as such we'll handle them on a case-by-case basis. - + - In some cases this is of course unavoidable, as such we'll handle them on a case-by-case basis. + Ultimately if you're looking to contribute, it's best to check in with us on Discord to see if we're already working on a specific feature or have plans for it already. Add us at **Tyn#0001** - -## Code Style - -We do have a few coding styles and lint rules we'd like all contributors to adhere to. **Please run the linter via `npm run lint` before submitting any Pull Requests**: - -- 4 space indentation -- Spaces between TS/ES6 import/export braces - - `import { this } from 'that';` instead of `import {this} from 'that';` -- Semicolon line endings - - `let myVariable = true;` instead of only `let myVariable = true` -- Single quotes instead of double quotes - - `let myString = 'hello world!';` instead of `let myString = "hello world";` - - `import { this } from 'that';` instead of `import { this } from "that";` -- Avoid the `var` keyword - - `let myVariable;` instead of `var myVariable;` -- Prefer `const` to `let` - - If a variable is never going to be modified, please declare it using `const` instead of `let` - - `const neverChanged = true;` instead of `let neverChanged = true;` -- Add types to all method parameters and return types to all methods - - `public myMethod(firstParam: string, secondParam: number): void {` instead of `public myMethod(firstParam, secondParam) {` -- Add `public`, `private`, or `protected` to every class variable or method - - `public myMethod(): void {` instead of `myMethod(): void {` - - `private myVar: number;` instead of `myVar: number;` -- Use TypeScript getters/setters instead of specific getter/setter methods - - `public get myVar(): number` instead of `public getMyVar(): number` - - `public set myVar(myVar: number)` instead of `public setMyVar(myVar: number)` ## Testing @@ -75,4 +49,6 @@ describe('when there is a player', () => { There are two main benefits to this kind of design: - It serves as living documentation: from reading the `beforeEach` block you can clearly see how the prerequisite of "player is wearing a hat" is achieved -- It allows for easy expansion of test cases: future developers can add further statements inside "when player is wearing a hat" if they want to make use of that setup \ No newline at end of file +- It allows for easy expansion of test cases: future developers can add further + statements inside "when player is wearing a hat" if they want to make use of + that setup diff --git a/README.md b/README.md index 6ca7dfcaa..70c5d3020 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,3 @@ Before running these commands, you must: * `npm run standalone` Launches all three servers concurrently without building * `npm run build:watch` Builds the application and watches for changes * `npm run build` Builds the application -* `npm run lint` Runs the linter against the codebase to look for code style issues diff --git a/package-lock.json b/package-lock.json index 4abe96c6a..394057abe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,6 @@ "uuid": "^11.0.5" }, "devDependencies": { - "@runejs/eslint-config": "^1.1.0", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.9", "@types/jest": "^29.5.14", @@ -31,12 +30,8 @@ "@types/lodash": "^4.17.14", "@types/node": "^22.10.8", "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^5.14.0", - "@typescript-eslint/parser": "^5.14.0", "chokidar": "^4.0.3", "concurrently": "^9.1.2", - "eslint": "^8.57.0", - "eslint-plugin-unused-imports": "^2.0.0", "jest": "^29.7.0", "nodemon": "^3.1.9", "rimraf": "^6.0.1", @@ -46,15 +41,6 @@ "typescript": "^5.7.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": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -570,127 +556,11 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@hapi/bourne": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz", "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1717,17 +1587,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@runejs/eslint-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@runejs/eslint-config/-/eslint-config-1.1.0.tgz", - "integrity": "sha512-mNfYgw5/ZBnivE2h5MnMohbneHOzW0qyCVrNlhiW2Cn0iYfaAX4YQSlU6xA4oC/vIn/3R3zenJAxBip0Iyt2dg==", - "dev": true, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=5.14.0", - "@typescript-eslint/parser": ">=5.14.0", - "eslint": ">=8" - } - }, "node_modules/@runejs/filestore": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/@runejs/filestore/-/filestore-0.17.0.tgz", @@ -2298,12 +2157,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "node_modules/@types/lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", @@ -2321,12 +2174,6 @@ "undici-types": "~6.20.0" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2346,452 +2193,159 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "node_modules/@xhmikosr/archive-type": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@xhmikosr/archive-type/-/archive-type-7.0.0.tgz", + "integrity": "sha512-sIm84ZneCOJuiy3PpWR5bxkx3HaNt1pqaN+vncUBZIlPZCq8ASZH+hBVdu5H8znR7qYC6sKwx+ie2Q7qztJTxA==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "file-type": "^19.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": "^14.14.0 || >=16.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@xhmikosr/bin-check": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@xhmikosr/bin-check/-/bin-check-7.0.3.tgz", + "integrity": "sha512-4UnCLCs8DB+itHJVkqFp9Zjg+w/205/J2j2wNBsCEAm/BuBmtua2hhUOdAMQE47b1c7P9Xmddj0p+X1XVsfHsA==", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "execa": "^5.1.1", + "isexe": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/@xhmikosr/bin-wrapper": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@xhmikosr/bin-wrapper/-/bin-wrapper-13.0.5.tgz", + "integrity": "sha512-DT2SAuHDeOw0G5bs7wZbQTbf4hd8pJ14tO0i4cWhRkIJfgRdKmMfkDilpaJ8uZyPA0NVRwasCNAmMJcWA67osw==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@xhmikosr/bin-check": "^7.0.3", + "@xhmikosr/downloader": "^15.0.1", + "@xhmikosr/os-filter-obj": "^3.0.0", + "bin-version-check": "^5.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "node_modules/@xhmikosr/decompress": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@xhmikosr/decompress/-/decompress-10.0.1.tgz", + "integrity": "sha512-6uHnEEt5jv9ro0CDzqWlFgPycdE+H+kbJnwyxgZregIMLQ7unQSCNVsYG255FoqU8cP46DyggI7F7LohzEl8Ag==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" + "@xhmikosr/decompress-tar": "^8.0.1", + "@xhmikosr/decompress-tarbz2": "^8.0.1", + "@xhmikosr/decompress-targz": "^8.0.1", + "@xhmikosr/decompress-unzip": "^7.0.0", + "graceful-fs": "^4.2.11", + "make-dir": "^4.0.0", + "strip-dirs": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/@xhmikosr/decompress-tar": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tar/-/decompress-tar-8.0.1.tgz", + "integrity": "sha512-dpEgs0cQKJ2xpIaGSO0hrzz3Kt8TQHYdizHsgDtLorWajuHJqxzot9Hbi0huRxJuAGG2qiHSQkwyvHHQtlE+fg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "file-type": "^19.0.0", + "is-stream": "^2.0.1", + "tar-stream": "^3.1.7" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=18" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "node_modules/@xhmikosr/decompress-tarbz2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tarbz2/-/decompress-tarbz2-8.0.2.tgz", + "integrity": "sha512-p5A2r/AVynTQSsF34Pig6olt9CvRj6J5ikIhzUd3b57pUXyFDGtmBstcw+xXza0QFUh93zJsmY3zGeNDlR2AQQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" + "@xhmikosr/decompress-tar": "^8.0.1", + "file-type": "^19.6.0", + "is-stream": "^2.0.1", + "seek-bzip": "^2.0.0", + "unbzip2-stream": "^1.4.3" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=18" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/@xhmikosr/decompress-targz": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-targz/-/decompress-targz-8.0.1.tgz", + "integrity": "sha512-mvy5AIDIZjQ2IagMI/wvauEiSNHhu/g65qpdM4EVoYHUJBAmkQWqcPJa8Xzi1aKVTmOA5xLJeDk7dqSjlHq8Mg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@xhmikosr/decompress-tar": "^8.0.1", + "file-type": "^19.0.0", + "is-stream": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@xhmikosr/decompress-unzip": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-unzip/-/decompress-unzip-7.0.0.tgz", + "integrity": "sha512-GQMpzIpWTsNr6UZbISawsGI0hJ4KA/mz5nFq+cEoPs12UybAqZWKbyIaZZyLbJebKl5FkLpsGBkrplJdjvUoSQ==", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "file-type": "^19.0.0", + "get-stream": "^6.0.1", + "yauzl": "^3.1.2" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/@xhmikosr/downloader": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@xhmikosr/downloader/-/downloader-15.0.1.tgz", + "integrity": "sha512-fiuFHf3Dt6pkX8HQrVBsK0uXtkgkVlhrZEh8b7VgoDqFf+zrgFBPyrwCqE/3nDwn3hLeNz+BsrS7q3mu13Lp1g==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@xhmikosr/archive-type": "^7.0.0", + "@xhmikosr/decompress": "^10.0.1", + "content-disposition": "^0.5.4", + "defaults": "^3.0.0", + "ext-name": "^5.0.0", + "file-type": "^19.0.0", + "filenamify": "^6.0.0", + "get-stream": "^6.0.1", + "got": "^13.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/@xhmikosr/os-filter-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@xhmikosr/os-filter-obj/-/os-filter-obj-3.0.0.tgz", + "integrity": "sha512-siPY6BD5dQ2SZPl3I0OZBHL27ZqZvLEosObsZRQ1NUB8qcxegwt0T9eKtV96JMFQpIz1elhkzqOg4c/Ri6Dp9A==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@xhmikosr/archive-type": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@xhmikosr/archive-type/-/archive-type-7.0.0.tgz", - "integrity": "sha512-sIm84ZneCOJuiy3PpWR5bxkx3HaNt1pqaN+vncUBZIlPZCq8ASZH+hBVdu5H8znR7qYC6sKwx+ie2Q7qztJTxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "file-type": "^19.0.0" - }, - "engines": { - "node": "^14.14.0 || >=16.0.0" - } - }, - "node_modules/@xhmikosr/bin-check": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@xhmikosr/bin-check/-/bin-check-7.0.3.tgz", - "integrity": "sha512-4UnCLCs8DB+itHJVkqFp9Zjg+w/205/J2j2wNBsCEAm/BuBmtua2hhUOdAMQE47b1c7P9Xmddj0p+X1XVsfHsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.1.1", - "isexe": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/bin-wrapper": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@xhmikosr/bin-wrapper/-/bin-wrapper-13.0.5.tgz", - "integrity": "sha512-DT2SAuHDeOw0G5bs7wZbQTbf4hd8pJ14tO0i4cWhRkIJfgRdKmMfkDilpaJ8uZyPA0NVRwasCNAmMJcWA67osw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xhmikosr/bin-check": "^7.0.3", - "@xhmikosr/downloader": "^15.0.1", - "@xhmikosr/os-filter-obj": "^3.0.0", - "bin-version-check": "^5.1.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/decompress": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@xhmikosr/decompress/-/decompress-10.0.1.tgz", - "integrity": "sha512-6uHnEEt5jv9ro0CDzqWlFgPycdE+H+kbJnwyxgZregIMLQ7unQSCNVsYG255FoqU8cP46DyggI7F7LohzEl8Ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xhmikosr/decompress-tar": "^8.0.1", - "@xhmikosr/decompress-tarbz2": "^8.0.1", - "@xhmikosr/decompress-targz": "^8.0.1", - "@xhmikosr/decompress-unzip": "^7.0.0", - "graceful-fs": "^4.2.11", - "make-dir": "^4.0.0", - "strip-dirs": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/decompress-tar": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tar/-/decompress-tar-8.0.1.tgz", - "integrity": "sha512-dpEgs0cQKJ2xpIaGSO0hrzz3Kt8TQHYdizHsgDtLorWajuHJqxzot9Hbi0huRxJuAGG2qiHSQkwyvHHQtlE+fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "file-type": "^19.0.0", - "is-stream": "^2.0.1", - "tar-stream": "^3.1.7" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/decompress-tarbz2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tarbz2/-/decompress-tarbz2-8.0.2.tgz", - "integrity": "sha512-p5A2r/AVynTQSsF34Pig6olt9CvRj6J5ikIhzUd3b57pUXyFDGtmBstcw+xXza0QFUh93zJsmY3zGeNDlR2AQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xhmikosr/decompress-tar": "^8.0.1", - "file-type": "^19.6.0", - "is-stream": "^2.0.1", - "seek-bzip": "^2.0.0", - "unbzip2-stream": "^1.4.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/decompress-targz": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-targz/-/decompress-targz-8.0.1.tgz", - "integrity": "sha512-mvy5AIDIZjQ2IagMI/wvauEiSNHhu/g65qpdM4EVoYHUJBAmkQWqcPJa8Xzi1aKVTmOA5xLJeDk7dqSjlHq8Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xhmikosr/decompress-tar": "^8.0.1", - "file-type": "^19.0.0", - "is-stream": "^2.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/decompress-unzip": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-unzip/-/decompress-unzip-7.0.0.tgz", - "integrity": "sha512-GQMpzIpWTsNr6UZbISawsGI0hJ4KA/mz5nFq+cEoPs12UybAqZWKbyIaZZyLbJebKl5FkLpsGBkrplJdjvUoSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "file-type": "^19.0.0", - "get-stream": "^6.0.1", - "yauzl": "^3.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/downloader": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@xhmikosr/downloader/-/downloader-15.0.1.tgz", - "integrity": "sha512-fiuFHf3Dt6pkX8HQrVBsK0uXtkgkVlhrZEh8b7VgoDqFf+zrgFBPyrwCqE/3nDwn3hLeNz+BsrS7q3mu13Lp1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xhmikosr/archive-type": "^7.0.0", - "@xhmikosr/decompress": "^10.0.1", - "content-disposition": "^0.5.4", - "defaults": "^3.0.0", - "ext-name": "^5.0.0", - "file-type": "^19.0.0", - "filenamify": "^6.0.0", - "get-stream": "^6.0.1", - "got": "^13.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@xhmikosr/os-filter-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@xhmikosr/os-filter-obj/-/os-filter-obj-3.0.0.tgz", - "integrity": "sha512-siPY6BD5dQ2SZPl3I0OZBHL27ZqZvLEosObsZRQ1NUB8qcxegwt0T9eKtV96JMFQpIz1elhkzqOg4c/Ri6Dp9A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arch": "^3.0.0" + "arch": "^3.0.0" }, "engines": { "node": "^14.14.0 || >=16.0.0" @@ -2815,15 +2369,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", @@ -2833,22 +2378,6 @@ "node": ">=0.4.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -2968,15 +2497,6 @@ "node": ">=0.10.0" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -3966,12 +3486,6 @@ "node": ">=4.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -4007,490 +3521,131 @@ "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.686", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.686.tgz", - "integrity": "sha512-3avY1B+vUzNxEgkBDpKOP8WarvUAEwpRaiCL0He5OKWEFxzaOFiq4WoZEZe7qh0ReS7DiWoHMnYoQCKxNZNzSg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-rule-composer": "^0.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.3.1" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "jake": "^10.8.5" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "ejs": "bin/cli.js" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/electron-to-chromium": { + "version": "1.4.686", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.686.tgz", + "integrity": "sha512-3avY1B+vUzNxEgkBDpKOP8WarvUAEwpRaiCL0He5OKWEFxzaOFiq4WoZEZe7qh0ReS7DiWoHMnYoQCKxNZNzSg==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, "engines": { - "node": ">=0.10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=4.0" + "node": ">=0.8.0" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/execa": { @@ -4577,12 +3732,6 @@ "node": ">=4" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -4612,12 +3761,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, "node_modules/fast-redact": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", @@ -4649,18 +3792,6 @@ "bser": "2.1.1" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, "node_modules/file-type": { "version": "19.6.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-19.6.0.tgz", @@ -4784,31 +3915,6 @@ "node": ">=8" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/find-versions": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", @@ -4825,48 +3931,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/flatstr": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -5028,35 +4097,6 @@ "node": ">=4" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/got": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", @@ -5094,12 +4134,6 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5175,37 +4209,12 @@ } ] }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -5417,15 +4426,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -7375,18 +6375,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -7435,40 +6423,12 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -7480,12 +6440,6 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, "node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -7675,12 +6629,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", @@ -7914,23 +6862,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -7956,21 +6887,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -7987,18 +6903,6 @@ "dev": true, "license": "BlueOak-1.0.0" }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -8068,15 +6972,6 @@ "node": "20 || >=22" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/peek-readable": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.4.2.tgz", @@ -8286,15 +7181,6 @@ "node": ">=10" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -8363,15 +7249,6 @@ "once": "^1.3.1" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -8542,15 +7419,6 @@ "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -9242,12 +8110,6 @@ "b4a": "^1.6.4" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9471,27 +8333,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -9504,18 +8345,6 @@ "node": "*" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -9642,15 +8471,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9921,12 +8741,6 @@ } }, "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.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -10311,89 +9125,11 @@ } } }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true - }, "@hapi/bourne": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz", "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" }, - "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -11161,13 +9897,6 @@ } } }, - "@runejs/eslint-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@runejs/eslint-config/-/eslint-config-1.1.0.tgz", - "integrity": "sha512-mNfYgw5/ZBnivE2h5MnMohbneHOzW0qyCVrNlhiW2Cn0iYfaAX4YQSlU6xA4oC/vIn/3R3zenJAxBip0Iyt2dg==", - "dev": true, - "requires": {} - }, "@runejs/filestore": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/@runejs/filestore/-/filestore-0.17.0.tgz", @@ -11548,12 +10277,6 @@ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "@types/lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", @@ -11569,12 +10292,6 @@ "undici-types": "~6.20.0" } }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -11593,189 +10310,6 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "@xhmikosr/archive-type": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@xhmikosr/archive-type/-/archive-type-7.0.0.tgz", @@ -11906,31 +10440,12 @@ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, "acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -12009,12 +10524,6 @@ } } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, "async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -12686,12 +11195,6 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, "deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -12733,24 +11236,6 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -12812,242 +11297,11 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, - "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "requires": { - "eslint-rule-composer": "^0.3.0" - } - }, - "eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -13108,12 +11362,6 @@ "sort-keys-length": "^1.0.0" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -13139,12 +11387,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, "fast-redact": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", @@ -13173,15 +11415,6 @@ "bser": "2.1.1" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, "file-type": { "version": "19.6.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-19.6.0.tgz", @@ -13265,24 +11498,6 @@ "to-regex-range": "^5.0.1" } }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, "find-versions": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", @@ -13292,39 +11507,11 @@ "semver-regex": "^4.0.5" } }, - "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "flatstr": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, "foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -13431,28 +11618,6 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - } - } - }, "got": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", @@ -13483,12 +11648,6 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -13536,28 +11695,12 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, - "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true - }, "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, "import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -13714,12 +11857,6 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -15154,18 +13291,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -15198,31 +13323,12 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -15234,12 +13340,6 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, "lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -15374,12 +13474,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", @@ -15546,20 +13640,6 @@ "mimic-fn": "^2.1.0" } }, - "optionator": { - "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" - } - }, "p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -15575,15 +13655,6 @@ "yocto-queue": "^0.1.0" } }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -15596,15 +13667,6 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -15653,12 +13715,6 @@ } } }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, "peek-readable": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.4.2.tgz", @@ -15816,12 +13872,6 @@ "tunnel-agent": "^0.6.0" } }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, "pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -15876,12 +13926,6 @@ "once": "^1.3.1" } }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, "pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -15990,12 +14034,6 @@ } } }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, "resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -16461,12 +14499,6 @@ "b4a": "^1.6.4" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -16600,23 +14632,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -16625,15 +14640,6 @@ "safe-buffer": "^5.0.1" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -16701,15 +14707,6 @@ "picocolors": "^1.0.0" } }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 605636136..c256c7ea5 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,6 @@ "update": "npm run start:update", "infra": "npm run start:infra", "standalone": "npm run start:standalone", - "lint": "eslint --ext .ts src", - "lint:fix": "eslint --ext .ts src --fix", "build": "rimraf dist && swc ./src -d dist --strip-leading-paths", "build:watch": "swc ./src -d dist -w --strip-leading-paths", "test": "jest", @@ -57,7 +55,6 @@ "uuid": "^11.0.5" }, "devDependencies": { - "@runejs/eslint-config": "^1.1.0", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.9", "@types/jest": "^29.5.14", @@ -65,12 +62,8 @@ "@types/lodash": "^4.17.14", "@types/node": "^22.10.8", "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^5.14.0", - "@typescript-eslint/parser": "^5.14.0", "chokidar": "^4.0.3", "concurrently": "^9.1.2", - "eslint": "^8.57.0", - "eslint-plugin-unused-imports": "^2.0.0", "jest": "^29.7.0", "nodemon": "^3.1.9", "rimraf": "^6.0.1", @@ -78,16 +71,5 @@ "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.7.3" - }, - "eslintConfig": { - "extends": ["@runejs/eslint-config"], - "plugins": ["unused-imports"], - "rules": { - "unused-imports/no-unused-imports": "error", - "@typescript-eslint/consistent-type-imports": "error" - }, - "parserOptions": { - "project": "./tsconfig.json" - } } } diff --git a/src/engine/action/hook/task.ts b/src/engine/action/hook/task.ts index 80ae28a16..cb213dfd0 100644 --- a/src/engine/action/hook/task.ts +++ b/src/engine/action/hook/task.ts @@ -57,7 +57,6 @@ export class TaskExecutor { public async run(): Promise { this.running = true; - /* eslint-disable @typescript-eslint/no-non-null-assertion */ if(!!this.task.delay || !!this.task.delayMs) { await lastValueFrom(timer(this.task.delayMs !== undefined ? this.task.delayMs : (this.task.delay! * World.TICK_LENGTH))); @@ -67,7 +66,6 @@ export class TaskExecutor { // Looping execution task const intervalMs = this.task.intervalMs !== undefined ? this.task.intervalMs : (this.task.interval! * World.TICK_LENGTH); - /* eslint-enable @typescript-eslint/no-non-null-assertion */ await new Promise(resolve => { this.intervalSubscription = timer(0, intervalMs).subscribe( diff --git a/src/engine/action/pipe/item-swap.action.ts b/src/engine/action/pipe/item-swap.action.ts index 8fc1a7b5b..c7194a0f4 100644 --- a/src/engine/action/pipe/item-swap.action.ts +++ b/src/engine/action/pipe/item-swap.action.ts @@ -48,7 +48,6 @@ const itemSwapActionPipe = (player: Player, fromSlot: number, toSlot: number, const matchingHooks = getActionHooks('item_swap') .filter(plugin => ( (plugin.widgetId || plugin.widgetIds) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) )); diff --git a/src/engine/action/pipe/move-item.action.ts b/src/engine/action/pipe/move-item.action.ts index 761386d41..e643a58f7 100644 --- a/src/engine/action/pipe/move-item.action.ts +++ b/src/engine/action/pipe/move-item.action.ts @@ -48,7 +48,6 @@ const moveItemActionPipe = (player: Player, fromSlot: number, toSlot: number, const matchingHooks = getActionHooks('move_item') .filter(plugin => ( (plugin.widgetId || plugin.widgetIds) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) )); diff --git a/src/engine/plugins/loader.ts b/src/engine/plugins/loader.ts index 341d2993f..8bdc05576 100644 --- a/src/engine/plugins/loader.ts +++ b/src/engine/plugins/loader.ts @@ -45,7 +45,6 @@ export async function loadPlugins(): Promise { actionHookMap[action.type] = []; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion actionHookMap[action.type]!.push(action); } else { if(!actionHookMap['quest']) { diff --git a/src/engine/util/strings.ts b/src/engine/util/strings.ts index a2f5a21a0..ae4c4d7b1 100644 --- a/src/engine/util/strings.ts +++ b/src/engine/util/strings.ts @@ -80,12 +80,9 @@ export function wrapText(text: string, maxWidth: number, font?: number | string) break; case '>': hidden = true; - // eslint-disable-next-line no-case-declarations const currentTag = currentLine.substring(currentTagIndex, currentLine.length); currentTagIndex = -1; - // eslint-disable-next-line no-case-declarations const isClosing = currentTag.charAt(0) === '/'; - // eslint-disable-next-line no-case-declarations const type = getStylingType(currentTag); if (type === TextDecoration.Decoration) { if (!isClosing) { diff --git a/src/engine/world/instances.ts b/src/engine/world/instances.ts index 0ea4e108c..1ca389747 100644 --- a/src/engine/world/instances.ts +++ b/src/engine/world/instances.ts @@ -454,10 +454,8 @@ export class WorldInstance { x: worldPositionOrX, // using ! here because we know that if the first parameter is a number, the other two will be too - /* eslint-disable @typescript-eslint/no-non-null-assertion */ y: y!, level: level! - /* eslint-enable @typescript-eslint/no-non-null-assertion */ }); if(chunk) { @@ -486,7 +484,6 @@ export class WorldInstance { } // using ! here because we know the chunk exists, as we've just created it if it didn't - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.chunkModifications.get(chunkPosition.key)!; } @@ -500,7 +497,6 @@ export class WorldInstance { return { chunk: instancedChunk, // using ! here because we know it exists - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion mods: instancedChunk.mods.get(worldPosition.key)! }; } diff --git a/src/engine/world/items/item-container.ts b/src/engine/world/items/item-container.ts index 8320e2c39..213a41fb4 100644 --- a/src/engine/world/items/item-container.ts +++ b/src/engine/world/items/item-container.ts @@ -173,7 +173,6 @@ export class ItemContainer { const newItem = { itemId: item.itemId, // using ! here because we know the item exists in the inventory - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion amount: this._items[existingItemIndex]!.amount += item.amount } as Item; @@ -214,7 +213,6 @@ export class ItemContainer { const newItem = { itemId: item.itemId, // using ! here because we know the item exists in the inventory - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion amount: this._items[existingItemIndex]!.amount += item.amount } as Item; @@ -340,7 +338,6 @@ export class ItemContainer { if(itemDefinition.stackable || everythingStacks || fromNote(item) > -1) { if(this.has(item.itemId)) { // using ! here because we know that we have the item in the inventory - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const invItem = this.items[this.findIndex(item.itemId)]!; return invItem.amount + item.amount <= 2147483647; } diff --git a/src/engine/world/map/chunk-manager.ts b/src/engine/world/map/chunk-manager.ts index 61174c57d..f4724455c 100644 --- a/src/engine/world/map/chunk-manager.ts +++ b/src/engine/world/map/chunk-manager.ts @@ -175,7 +175,6 @@ export class ChunkManager { const pos = (position as Position); if(this.chunkMap.has(pos.key)) { // using ! here because we know it exists - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.chunkMap.get(pos.key)!; } else { const chunk = new Chunk(pos); diff --git a/src/engine/world/map/collision-map.ts b/src/engine/world/map/collision-map.ts index 692dc71c3..2bef5b482 100644 --- a/src/engine/world/map/collision-map.ts +++ b/src/engine/world/map/collision-map.ts @@ -358,11 +358,9 @@ export class CollisionMap { } if(mark) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._adjacency[x][y] |= 0x200000; } else { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._adjacency[x][y] &= 0xdfffff; } @@ -400,7 +398,6 @@ export class CollisionMap { this._adjacency[x][y] = 0; } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._adjacency[x][y] |= flag; } @@ -430,7 +427,6 @@ export class CollisionMap { this._adjacency[x][y] = 0; } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._adjacency[x][y] &= 0xffffff - flag; } diff --git a/src/engine/world/position.ts b/src/engine/world/position.ts index 90ee9d75b..bb516394d 100644 --- a/src/engine/world/position.ts +++ b/src/engine/world/position.ts @@ -36,7 +36,6 @@ export class Position { public constructor(arg0: number | Coords | Position, y?: number, level?: number) { if(typeof arg0 === 'number') { // using ! here, because we know that if arg0 is a number, then y and level are numbers - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.move(arg0, y!, level); } else { this.move(arg0.x, arg0.y, arg0.level); diff --git a/src/plugins/items/herblore/clean-herb.ts b/src/plugins/items/herblore/clean-herb.ts index 77f4cbe7c..785b48f6d 100644 --- a/src/plugins/items/herblore/clean-herb.ts +++ b/src/plugins/items/herblore/clean-herb.ts @@ -17,7 +17,6 @@ interface IGrimyHerb { * (Jameskmonger) I have put ! after findItem() because we know the items exist. */ const herbs: IGrimyHerb[] = [ - /* eslint-disable @typescript-eslint/no-non-null-assertion */ { grimy: findItem('rs:grimy_guam')!, clean: findItem('rs:herb_guam')!, @@ -102,7 +101,6 @@ const herbs: IGrimyHerb[] = [ level: 75, experience: 15 }, - /* eslint-enable @typescript-eslint/no-non-null-assertion */ ] diff --git a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts index 513eaa781..2a0f3700a 100644 --- a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts +++ b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts @@ -9,7 +9,6 @@ import type { WidgetInteractionAction } from '@engine/action/pipe/widget-interac * * (Jameskmonger) I have put ! after findItem() because we know the item exists. */ -// eslint-disable-next-line @typescript-eslint/no-non-null-assertion export const RottenPotatoItem: ItemDetails = findItem('rs:rotten_potato')!; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts index 22c8a5072..af1370cde 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts @@ -33,7 +33,6 @@ const eatPotato: itemInteractionActionHandler = async (details) => { ] ]); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion switch (chosenOption!) { case DialogueOption.SET_ALL_STATS: break; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts index 00f81b0bf..e38fb9dd1 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts @@ -63,7 +63,6 @@ const peelPotato: itemInteractionActionHandler = async (details) => { ]); // using ! here because we have just set it in the dialogue - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion switch (chosenOption!) { case DialogueOption.BANK: openBank(details.player); diff --git a/src/plugins/items/shopping/sell-to-shop.plugin.ts b/src/plugins/items/shopping/sell-to-shop.plugin.ts index e241304e9..f4266dc9d 100644 --- a/src/plugins/items/shopping/sell-to-shop.plugin.ts +++ b/src/plugins/items/shopping/sell-to-shop.plugin.ts @@ -87,7 +87,6 @@ export const handler: itemInteractionActionHandler = (details) => { inventory.set(coinsIndex, { itemId: itemIds.coins, amount: sellPrice }); } else { // TODO (Jameskmonger) consider being explicit to prevent dupes - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion inventory.items[coinsIndex]!.amount += sellPrice; } } diff --git a/src/plugins/objects/crates/crates.plugin.ts b/src/plugins/objects/crates/crates.plugin.ts index d7412397c..27e5358f0 100644 --- a/src/plugins/objects/crates/crates.plugin.ts +++ b/src/plugins/objects/crates/crates.plugin.ts @@ -8,7 +8,6 @@ export const action: objectInteractionActionHandler = (details) => { details.player.playAnimation(827); const random = Math.floor(Math.random() * veggies.length); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const pickedItem = findItem(veggies[random])!; details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); diff --git a/src/plugins/player/follow-player.plugin.js b/src/plugins/player/follow-player.plugin.js index 7db2f759c..6ddb98538 100644 --- a/src/plugins/player/follow-player.plugin.js +++ b/src/plugins/player/follow-player.plugin.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-undef module.exports = { pluginId: 'rs:follow_player', hooks: [ diff --git a/src/plugins/skills/firemaking/data.ts b/src/plugins/skills/firemaking/data.ts index f1e7a857f..fdfeecb32 100644 --- a/src/plugins/skills/firemaking/data.ts +++ b/src/plugins/skills/firemaking/data.ts @@ -5,56 +5,48 @@ import type { Burnable } from './types'; export const FIREMAKING_LOGS: Burnable[] = [ { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:logs')!, requiredLevel: 1, experienceGained: 40 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:oak_logs')!, requiredLevel: 15, experienceGained: 60 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:willow_logs')!, requiredLevel: 30, experienceGained: 90 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:teak_logs')!, requiredLevel: 35, experienceGained: 105 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:maple_logs')!, requiredLevel: 45, experienceGained: 135 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:mahogany_logs')!, requiredLevel: 50, experienceGained: 157.5 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:yew_logs')!, requiredLevel: 60, experienceGained: 202.5 }, { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion logItem: findItem('rs:magic_logs')!, requiredLevel: 75, experienceGained: 303.8 From 40c4e3bbd6a3e80ac92e199f21bd20f696ecabc8 Mon Sep 17 00:00:00 2001 From: Borig Date: Sat, 1 Feb 2025 16:57:03 +1300 Subject: [PATCH 2/4] Add Biome to project with all violated lint rules disabled --- biome.json | 78 +++++++++++++++ package-lock.json | 237 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 + 3 files changed, 320 insertions(+) create mode 100644 biome.json diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..825268c3b --- /dev/null +++ b/biome.json @@ -0,0 +1,78 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false, + "ignore": [] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 140 + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "recommended": true, + "noBannedTypes": "off", + "noForEach": "off", + "noStaticOnlyClass": "off", + "noUselessConstructor": "off", + "noUselessSwitchCase": "off", + "useLiteralKeys": "off", + "useOptionalChain": "off" + }, + "correctness": { + "recommended": true, + "noSwitchDeclarations": "off" + }, + "performance": { + "recommended": true, + "noAccumulatingSpread": "off", + "noDelete": "off" + }, + "suspicious": { + "recommended": true, + "noAssignInExpressions": "off", + "noConfusingVoidType": "off", + "noDoubleEquals": "off", + "noDuplicateObjectKeys": "off", + "noExplicitAny": "off", + "noGlobalIsNan": "off", + "noImplicitAnyLet": "off", + "noSelfCompare": "off", + "noUnsafeDeclarationMerging": "off" + }, + "style": { + "recommended": true, + "noInferrableTypes": "off", + "noNonNullAssertion": "off", + "noParameterAssign": "off", + "noUnusedTemplateLiteral": "off", + "noUselessElse": "off", + "useEnumInitializers": "off", + "useImportType": "off", + "useNodejsImportProtocol": "off", + "useNumberNamespace": "off", + "useSingleVarDeclarator": "off", + "useTemplate": "off" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "arrowParentheses": "asNeeded" + } + } +} diff --git a/package-lock.json b/package-lock.json index 394057abe..adf96e620 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "uuid": "^11.0.5" }, "devDependencies": { + "@biomejs/biome": "1.9.4", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.9", "@types/jest": "^29.5.14", @@ -534,6 +535,170 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -9104,6 +9269,78 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "requires": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "dev": true, + "optional": true + }, "@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", diff --git a/package.json b/package.json index c256c7ea5..7c7c7b7b5 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,10 @@ "standalone": "npm run start:standalone", "build": "rimraf dist && swc ./src -d dist --strip-leading-paths", "build:watch": "swc ./src -d dist -w --strip-leading-paths", + "lint": "biome lint", + "lint:fix": "biome lint --write", + "format": "biome format", + "format:fix": "biome format --write", "test": "jest", "test:fin": "jest --silent --reporters=\"summary\"", "typecheck": "tsc -p ./ --noEmit" @@ -55,6 +59,7 @@ "uuid": "^11.0.5" }, "devDependencies": { + "@biomejs/biome": "1.9.4", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.9", "@types/jest": "^29.5.14", From 08d87bd5eccb4d70c7d8663461a1f57df024aa86 Mon Sep 17 00:00:00 2001 From: Borig Date: Sat, 1 Feb 2025 16:57:21 +1300 Subject: [PATCH 3/4] Auto-format with Biome --- .swcrc | 2 +- .vscode/settings.json | 8 +- data/config/items/barrows/dharoks.json | 2 +- data/config/items/currency.json | 2 +- data/config/items/equipment/amulets.json | 104 +- data/config/items/equipment/halberd.json | 6 +- data/config/items/equipment/slayer.json | 840 +-- data/config/items/equipment/spears.json | 14 +- .../standard-metals/rune-armour.json | 2 +- .../standard-metals/rune-god-armour.json | 6 +- .../standard-metals/white-armour.json | 2 +- data/config/items/equipment/whips.json | 150 +- data/config/items/food.json | 49 +- data/config/items/holiday/partyhats.json | 2 +- data/config/items/logs.json | 10 +- data/config/items/quests/lost-city.json | 14 +- data/config/items/skills/herblore.json | 3 - data/config/items/skills/herblore/herbs.json | 244 +- data/config/items/skills/herblore/tools.json | 12 +- data/config/items/skills/mining.json | 4 +- data/config/items/skills/prayer.json | 3 +- data/config/items/skills/runecrafting.json | 26 +- data/config/music/musicRegions.json | 6123 +++++++---------- data/config/npc-spawns/ardougne/guards.json | 126 +- data/config/npc-spawns/falador/guards.json | 42 +- .../npc-spawns/pestcontrol/bankers.json | 3 +- data/config/npcs/ardougne.json | 16 +- data/config/npcs/general.json | 5 +- data/config/npcs/goblins.json | 6 +- data/config/npcs/guards.json | 72 +- .../shops/alkharid/alkharid-gem-trader.json | 96 +- .../alkharid/dommiks-crafting-store.json | 106 +- .../shops/alkharid/louies-armored-legs.json | 76 +- .../shops/alkharid/ranaels-skirt-store.json | 76 +- data/config/shops/lumbridge/bobs-axes.json | 86 +- .../lumbridge/lumbridge-general-store.json | 128 +- .../portsarim/bettys-magic-emporium.json | 126 +- .../shilo-village/oblis-general-store.json | 248 +- data/config/shops/varrock/zaffs-staffs.json | 86 +- data/config/widgets.json | 226 +- data/config/xteas/435.json | 2373 +------ data/config/xteas/468.json | 14 +- jest.config.ts | 284 +- nodemon.json | 2 +- package.json | 8 +- src/engine/action/action-pipeline.ts | 70 +- src/engine/action/hook/action-hook.ts | 9 +- src/engine/action/hook/hook-filters.test.ts | 33 +- src/engine/action/hook/hook-filters.ts | 51 +- src/engine/action/hook/task.ts | 67 +- src/engine/action/loader.ts | 11 +- src/engine/action/pipe/button.action.ts | 34 +- .../action/pipe/equipment-change.action.ts | 42 +- .../action/pipe/item-interaction.action.ts | 66 +- src/engine/action/pipe/item-on-item.action.ts | 49 +- src/engine/action/pipe/item-on-npc.action.ts | 57 +- .../action/pipe/item-on-object.action.ts | 64 +- .../action/pipe/item-on-player.action.ts | 50 +- .../action/pipe/item-on-world-item.action.ts | 42 +- src/engine/action/pipe/item-swap.action.ts | 34 +- src/engine/action/pipe/magic-on-npc.action.ts | 18 +- src/engine/action/pipe/move-item.action.ts | 34 +- src/engine/action/pipe/npc-init.action.ts | 11 +- .../action/pipe/npc-interaction.action.ts | 43 +- .../action/pipe/object-interaction.action.ts | 45 +- .../action/pipe/player-command.action.ts | 51 +- src/engine/action/pipe/player-init.action.ts | 6 +- .../action/pipe/player-interaction.action.ts | 29 +- src/engine/action/pipe/prayer.action.ts | 18 +- .../action/pipe/region-change.action.ts | 95 +- .../pipe/spawned-item-interaction.action.ts | 36 +- src/engine/action/pipe/task/queueable-task.ts | 36 +- .../pipe/task/walk-to-actor-plugin-task.ts | 31 +- .../pipe/task/walk-to-item-plugin-task.ts | 17 +- .../pipe/task/walk-to-object-plugin-task.ts | 12 +- .../action/pipe/widget-interaction.action.ts | 40 +- src/engine/config/config-handler.ts | 82 +- src/engine/config/data-dump.ts | 15 +- src/engine/config/item-config.ts | 149 +- src/engine/config/item-spawn-config.ts | 10 +- src/engine/config/music-regions-config.ts | 2 - src/engine/config/npc-config.ts | 66 +- src/engine/config/npc-spawn-config.ts | 16 +- src/engine/config/quest-config.ts | 16 +- src/engine/config/shop-config.test.ts | 85 +- src/engine/config/shop-config.ts | 57 +- src/engine/interface/interface-state.ts | 128 +- src/engine/net/inbound-packet-handler.ts | 10 +- .../net/inbound-packets/add-friend.packet.ts | 4 +- .../net/inbound-packets/add-ignore.packet.ts | 3 +- .../blinking-tab-click.packet.ts | 4 +- .../inbound-packets/button-click.packet.ts | 2 +- .../character-design.packet.ts | 8 +- src/engine/net/inbound-packets/chat.packet.ts | 2 +- .../net/inbound-packets/command.packet.ts | 27 +- .../net/inbound-packets/drop-item.packet.ts | 2 +- .../net/inbound-packets/examine.packet.ts | 40 +- .../item-interaction.packet.ts | 66 +- .../inbound-packets/item-on-item.packet.ts | 27 +- .../net/inbound-packets/item-on-npc.packet.ts | 19 +- .../inbound-packets/item-on-object.packet.ts | 38 +- .../inbound-packets/item-on-player.packet.ts | 32 +- .../item-on-world-item.packet.ts | 23 +- .../net/inbound-packets/item-swap.packet.ts | 14 +- src/engine/net/inbound-packets/junk.packet.ts | 34 +- .../inbound-packets/magic-attack.packet.ts | 15 +- .../inbound-packets/npc-interaction.packet.ts | 38 +- .../inbound-packets/number-input.packet.ts | 3 +- .../object-interaction.packet.ts | 43 +- .../net/inbound-packets/pickup-item.packet.ts | 8 +- .../player-interaction.packet.ts | 35 +- .../inbound-packets/private-message.packet.ts | 10 +- .../inbound-packets/remove-friend.packet.ts | 4 +- .../inbound-packets/remove-ignore.packet.ts | 3 +- .../inbound-packets/social-button.packet.ts | 4 +- src/engine/net/inbound-packets/walk.packet.ts | 34 +- .../widget-interaction.packet.ts | 3 +- .../inbound-packets/widgets-closed.packet.ts | 2 +- src/engine/net/isaac.ts | 143 +- src/engine/net/outbound-packet-handler.ts | 135 +- src/engine/net/packet.ts | 11 +- src/engine/plugins/content-plugin.ts | 20 +- src/engine/plugins/loader.ts | 37 +- src/engine/plugins/reload-content.ts | 23 +- .../task/impl/actor-actor-interaction-task.ts | 14 +- ...actor-landscape-object-interaction-task.ts | 10 +- src/engine/task/impl/actor-task.ts | 6 +- src/engine/task/impl/actor-teleport-task.ts | 7 +- src/engine/task/impl/actor-walk-to-task.ts | 35 +- .../impl/actor-world-item-interaction-task.ts | 12 +- src/engine/task/task-scheduler.test.ts | 6 +- src/engine/task/task-scheduler.ts | 8 +- src/engine/task/task.test.ts | 13 +- src/engine/task/task.ts | 2 +- src/engine/task/types.ts | 54 +- src/engine/task/utils/_testing.ts | 12 +- src/engine/util/address.ts | 4 +- src/engine/util/colors.ts | 8 +- src/engine/util/error-handling.ts | 11 +- src/engine/util/files.ts | 20 +- src/engine/util/objects.ts | 32 +- src/engine/util/queue.test.ts | 4 +- src/engine/util/strings.ts | 126 +- src/engine/util/time.ts | 2 +- src/engine/util/varbits.ts | 6 +- src/engine/world/actor/actor.ts | 198 +- src/engine/world/actor/combat.ts | 2 +- src/engine/world/actor/dialogue.ts | 185 +- src/engine/world/actor/magic.ts | 7 +- src/engine/world/actor/npc.ts | 86 +- src/engine/world/actor/pathfinding.ts | 288 +- src/engine/world/actor/player/achievements.ts | 27 +- src/engine/world/actor/player/attack.ts | 10 +- src/engine/world/actor/player/cutscenes.ts | 44 +- .../world/actor/player/dialogue-action.ts | 54 +- src/engine/world/actor/player/metadata.ts | 5 +- src/engine/world/actor/player/player-data.ts | 34 +- src/engine/world/actor/player/player.ts | 489 +- .../world/actor/player/private-messaging.ts | 30 +- src/engine/world/actor/player/quest.ts | 3 - .../world/actor/player/sync/actor-sync.ts | 73 +- .../world/actor/player/sync/npc-sync-task.ts | 69 +- .../actor/player/sync/player-sync-task.ts | 113 +- src/engine/world/actor/skills.ts | 130 +- src/engine/world/actor/update-flags.ts | 10 +- src/engine/world/actor/util.ts | 2 +- src/engine/world/actor/walking-queue.ts | 84 +- src/engine/world/config/animation-ids.ts | 4 +- src/engine/world/config/examine-data.ts | 10 +- src/engine/world/config/gfx-ids.ts | 2 +- src/engine/world/config/harvest-tool.ts | 10 +- src/engine/world/config/harvestable-object.ts | 199 +- src/engine/world/config/item-ids.ts | 32 +- src/engine/world/config/object-ids.ts | 40 +- src/engine/world/config/scenery-spawns.ts | 11 +- src/engine/world/config/songs.ts | 16 +- src/engine/world/config/sound-ids.ts | 6 +- src/engine/world/config/travel-locations.ts | 14 +- src/engine/world/config/widget.ts | 2 +- src/engine/world/direction.ts | 34 +- src/engine/world/index.ts | 1 - src/engine/world/instances.ts | 138 +- src/engine/world/items/item-container.ts | 92 +- src/engine/world/items/item.ts | 21 +- src/engine/world/items/world-item.ts | 5 +- src/engine/world/map/chunk-manager.ts | 56 +- src/engine/world/map/chunk.ts | 25 +- src/engine/world/map/collision-map.ts | 223 +- src/engine/world/map/region.ts | 68 +- src/engine/world/position.ts | 42 +- src/engine/world/skill-util/harvest-roll.ts | 1 - src/engine/world/skill-util/harvest-skill.ts | 6 +- src/engine/world/sound/music.ts | 6 +- src/engine/world/world.ts | 246 +- src/plugins/buttons/logout-button.plugin.ts | 12 +- src/plugins/buttons/magic-attack.plugin.ts | 36 +- src/plugins/buttons/magic-teleports.plugin.ts | 86 +- src/plugins/buttons/player-emotes.plugin.ts | 119 +- .../buttons/player-setting-button.plugin.ts | 29 +- src/plugins/combat/combat-styles.plugin.ts | 86 +- src/plugins/commands/bank-command.plugin.ts | 21 +- .../commands/camera-commands.plugin.ts | 104 +- .../clear-inventory-command.plugin.ts | 13 +- .../commands/client-config-command.plugin.ts | 16 +- .../current-position-command.plugin.ts | 10 +- .../commands/data-dump-command.plugin.ts | 27 +- .../commands/dump-metadata-command.plugin.ts | 24 +- .../commands/give-item-command.plugin.ts | 39 +- src/plugins/commands/groups-debug.plugin.ts | 30 +- .../commands/pathing-commands.plugin.ts | 18 +- .../player-animation-command.plugin.ts | 14 +- .../player-graphics-command.plugin.ts | 16 +- .../commands/quest-list-command.plugin.ts | 10 +- .../commands/region-debug-commands.plugin.ts | 72 +- .../commands/reset-camera-command.plugin.ts | 8 +- .../commands/sound-song-commands.plugin.ts | 40 +- .../commands/spawn-npc-command.plugin.ts | 28 +- .../commands/spawn-scenery-command.plugin.ts | 52 +- .../spawn-test-players-command.plugin.ts | 30 +- src/plugins/commands/stat-commands.plugin.ts | 20 +- .../commands/teleport-command.plugin.ts | 24 +- .../commands/transform-command.plugin.ts | 18 +- .../commands/travel-back-command.plugin.ts | 10 +- src/plugins/commands/travel-command.plugin.ts | 16 +- .../commands/widget-commands.plugin.ts | 24 +- .../dialogue/dialogue-option.plugin.ts | 15 +- src/plugins/dialogue/item-selection.plugin.ts | 10 +- .../items/buckets/empty-container.plugin.ts | 18 +- .../items/buckets/fill-container.plugin.ts | 20 +- .../items/capes/skillcape-emotes.plugin.ts | 26 +- .../items/consumables/eating.plugin.ts | 54 +- src/plugins/items/drop-item.plugin.ts | 59 +- .../items/equipment/equip-item.plugin.ts | 10 +- .../items/equipment/equipment-stats.plugin.ts | 10 +- .../items/equipment/unequip-item.plugin.ts | 21 +- src/plugins/items/herblore/clean-herb.ts | 45 +- src/plugins/items/move-item.plugin.ts | 37 +- src/plugins/items/pickup-item.plugin.ts | 29 +- src/plugins/items/pots/empty-pot.plugin.ts | 16 +- .../helpers/rotten-potato-helpers.ts | 10 +- .../helpers/rotten-potato-travel.ts | 140 +- .../hooks/rotten-potato-command-hook.ts | 5 +- .../rotten-potato/hooks/rotten-potato-eat.ts | 40 +- .../hooks/rotten-potato-item-on-item.ts | 8 +- .../hooks/rotten-potato-item-on-player.ts | 22 +- .../rotten-potato/hooks/rotten-potato-peel.ts | 57 +- .../rotten-potato/rotten-potato.plugin.ts | 44 +- .../items/runecrafting/tiaras.plugin.ts | 15 +- .../items/shopping/buy-from-shop.plugin.ts | 57 +- .../items/shopping/item-value.plugin.ts | 33 +- .../items/shopping/sell-to-shop.plugin.ts | 43 +- src/plugins/items/swap-items.plugin.ts | 24 +- src/plugins/music/music-regions.plugin.ts | 36 +- src/plugins/music/music-tab.plugin.ts | 27 +- .../al-kharid/dommik-crafting-shop.plugin.ts | 34 +- .../npcs/al-kharid/gem-trader.plugin.ts | 29 +- src/plugins/npcs/al-kharid/karim.plugin.ts | 94 +- .../al-kharid/louie-armoured-legs.plugin.ts | 20 +- .../al-kharid/ranael-super-skirt.plugin.ts | 20 +- .../npcs/falador/custom-guards.plugin.ts | 58 +- src/plugins/npcs/lumbridge/bob.plugin.ts | 7 +- src/plugins/npcs/lumbridge/hans.plugin.ts | 65 +- .../lumbridge-farm-helpers.plugin.ts | 194 +- .../npcs/lumbridge/shopkeeper.plugin.ts | 9 +- src/plugins/npcs/port-sarim/betty.plugin.ts | 50 +- .../npcs/varrock/blue-moon-inn.plugin.ts | 316 +- .../varrock/master-smithing-tutor.plugin.ts | 135 +- src/plugins/npcs/varrock/wilough.plugin.ts | 32 +- .../varrock/zaff-superior-staffs.plugin.ts | 74 +- src/plugins/objects/bank/bank.plugin.ts | 120 +- .../objects/bank/deposit-box.plugin.ts | 36 +- src/plugins/objects/cows/cow.plugin.ts | 45 +- src/plugins/objects/crates/crates.plugin.ts | 14 +- src/plugins/objects/doors/door.plugin.ts | 53 +- .../objects/doors/double-door.plugin.ts | 74 +- src/plugins/objects/doors/gate.plugin.ts | 81 +- .../taverly-dungeon-ladder.plugin.ts | 20 +- .../objects/item-spawns/take-axe.plugin.ts | 14 +- src/plugins/objects/ladders/ladder.plugin.ts | 54 +- src/plugins/objects/mill/flour-bin.plugin.ts | 41 +- .../objects/mill/hopper-controls.plugin.ts | 13 +- src/plugins/objects/mill/hopper.plugin.ts | 14 +- .../objects/pickables/pickables.plugin.ts | 15 +- src/plugins/player/follow-player.plugin.js | 6 +- .../player/login-unlock-emotes.plugin.ts | 7 +- .../player/login-update-settings.plugin.ts | 6 +- .../player/update-friends-list.plugin.ts | 6 +- .../quests/cooks-assistant-quest.plugin.ts | 321 +- .../goblin-diplomacy-quest.plugin.ts | 141 +- .../melee-tutor-dialogue.ts | 124 +- .../runescape-guide-dialogue.ts | 185 +- .../stage-handler.ts | 151 +- src/plugins/quests/quest-journal.plugin.ts | 49 +- .../quests/witchs-potion-quest.plugin.ts | 355 +- .../skills/construction/con-constants.ts | 50 +- src/plugins/skills/construction/home-saver.ts | 28 +- src/plugins/skills/construction/house.ts | 64 +- src/plugins/skills/construction/index.ts | 32 +- .../skills/construction/room-builder.ts | 104 +- src/plugins/skills/construction/util.ts | 7 +- .../skills/crafting/sheep-plugin.plugin.ts | 18 +- .../skills/crafting/spinning-wheel.plugin.ts | 62 +- src/plugins/skills/firemaking/chance.ts | 4 +- src/plugins/skills/firemaking/data.ts | 26 +- .../skills/firemaking/firemaking-task.ts | 7 +- src/plugins/skills/firemaking/index.ts | 27 +- src/plugins/skills/firemaking/light-fire.ts | 21 +- src/plugins/skills/firemaking/types.ts | 2 +- .../skills/fletching/fletching-constants.ts | 513 +- .../skills/fletching/fletching-types.ts | 2 +- .../skills/fletching/fletching.plugin.ts | 2 - .../skills/level-up-dialogue.plugin.ts | 15 +- src/plugins/skills/mining/chance.ts | 9 +- src/plugins/skills/mining/mining-task.ts | 35 +- src/plugins/skills/mining/mining.plugin.ts | 27 +- .../skills/mining/prospecting.plugin.ts | 24 +- .../skills/prayer/bury-bones.plugin.ts | 10 +- .../runecrafting/runecrafting-altar.plugin.ts | 45 +- .../runecrafting/runecrafting-constants.ts | 791 ++- .../runecrafting-crafting.plugin.ts | 42 +- .../runecrafting/runecrafting-tiara.plugin.ts | 19 +- src/plugins/skills/skill-guides/Strength.json | 132 +- src/plugins/skills/skill-guides/attack.json | 188 +- .../skills/skill-guides/construction.json | 4553 ++++++------ src/plugins/skills/skill-guides/cooking.json | 878 +-- src/plugins/skills/skill-guides/crafting.json | 1025 +-- src/plugins/skills/skill-guides/defence.json | 188 +- src/plugins/skills/skill-guides/farming.json | 862 +-- .../skills/skill-guides/firemaking.json | 458 +- src/plugins/skills/skill-guides/fishing.json | 328 +- src/plugins/skills/skill-guides/herblore.json | 473 +- src/plugins/skills/skill-guides/hitpoint.json | 572 +- src/plugins/skills/skill-guides/magic.json | 1624 ++--- src/plugins/skills/skill-guides/mining.json | 258 +- src/plugins/skills/skill-guides/prayer.json | 293 +- src/plugins/skills/skill-guides/ranged.json | 538 +- .../skills/skill-guides/runecrafting.json | 618 +- .../skills/skill-guides/skill-guide-config.ts | 12 +- .../skill-guides/skill-guides.plugin.ts | 47 +- src/plugins/skills/skill-guides/slayer.json | 531 +- src/plugins/skills/skill-guides/smithing.json | 4 +- src/plugins/skills/skill-guides/thieving.json | 645 +- .../skills/skill-guides/woodcutting.json | 210 +- .../skills/smithing/forging-constants.ts | 4451 +++++++----- src/plugins/skills/smithing/forging-task.ts | 12 +- src/plugins/skills/smithing/forging.plugin.ts | 67 +- .../skills/smithing/smelting-constants.ts | 106 +- src/plugins/skills/smithing/smelting-task.ts | 14 +- .../skills/smithing/smelting.plugin.ts | 36 +- src/plugins/skills/woodcutting/chance.ts | 9 +- src/plugins/skills/woodcutting/index.ts | 10 +- .../skills/woodcutting/woodcutting-task.ts | 72 +- src/server/game/game-server-connection.ts | 54 +- src/server/game/game-server.ts | 26 +- src/server/gateway/gateway-server.ts | 60 +- src/server/runner.ts | 57 +- tsconfig.json | 23 +- 357 files changed, 21715 insertions(+), 23001 deletions(-) diff --git a/.swcrc b/.swcrc index fa369b2c9..da2f0684e 100644 --- a/.swcrc +++ b/.swcrc @@ -20,4 +20,4 @@ "dynamicImport": false } } - } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 1ec61fe7b..7fd48c04a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { - "editor.tabSize": 4, - "files.trimTrailingWhitespace": true, - "files.trimFinalNewlines": true, - "files.insertFinalNewline": true + "editor.tabSize": 4, + "files.trimTrailingWhitespace": true, + "files.trimFinalNewlines": true, + "files.insertFinalNewline": true } diff --git a/data/config/items/barrows/dharoks.json b/data/config/items/barrows/dharoks.json index 538e18e27..4d854b89d 100644 --- a/data/config/items/barrows/dharoks.json +++ b/data/config/items/barrows/dharoks.json @@ -1,5 +1,5 @@ { - "rs:dharoks_axe" : { + "rs:dharoks_axe": { "tradable": true, "equippable": true, "equipment_data": { diff --git a/data/config/items/currency.json b/data/config/items/currency.json index 754e11aaa..e78629473 100644 --- a/data/config/items/currency.json +++ b/data/config/items/currency.json @@ -3,4 +3,4 @@ "game_id": 995, "tradable": true } -} \ No newline at end of file +} diff --git a/data/config/items/equipment/amulets.json b/data/config/items/equipment/amulets.json index c423a1402..252fb91fd 100644 --- a/data/config/items/equipment/amulets.json +++ b/data/config/items/equipment/amulets.json @@ -1,54 +1,54 @@ { - "rs:amulet_of_glory": { - "game_id": 1704, - "examine": "A very powerful dragonstone amulet.", - "tradable": true, - "weight": 0.01, - "equippable": true, - "equipment_data": { - "equipment_slot": "neck", - "offensive_bonuses": { - "stab": 10, - "slash": 10, - "crush": 10, - "magic": 10, - "ranged": 10 - }, - "defensive_bonuses": { - "stab": 3, - "slash": 3, - "crush": 3, - "magic": 3, - "ranged": 3 - }, - "skill_bonuses": { - "prayer": 3, - "strength": 6, - "ranged": 0, - "magic": 0 - } - }, - "variations": [ - { - "game_id": 1706, - "examine": "A dragonstone amulet with 1 magic charge.", - "suffix": "charged_1" - }, - { - "game_id": 1708, - "examine": "A dragonstone amulet with 2 magic charges.", - "suffix": "charged_2" - }, - { - "game_id": 1710, - "examine": "A dragonstone amulet with 3 magic charges.", - "suffix": "charged_3" - }, - { - "game_id": 1712, - "examine": "A dragonstone amulet with 4 magic charges.", - "suffix": "charged_4" - } - ] - } + "rs:amulet_of_glory": { + "game_id": 1704, + "examine": "A very powerful dragonstone amulet.", + "tradable": true, + "weight": 0.01, + "equippable": true, + "equipment_data": { + "equipment_slot": "neck", + "offensive_bonuses": { + "stab": 10, + "slash": 10, + "crush": 10, + "magic": 10, + "ranged": 10 + }, + "defensive_bonuses": { + "stab": 3, + "slash": 3, + "crush": 3, + "magic": 3, + "ranged": 3 + }, + "skill_bonuses": { + "prayer": 3, + "strength": 6, + "ranged": 0, + "magic": 0 + } + }, + "variations": [ + { + "game_id": 1706, + "examine": "A dragonstone amulet with 1 magic charge.", + "suffix": "charged_1" + }, + { + "game_id": 1708, + "examine": "A dragonstone amulet with 2 magic charges.", + "suffix": "charged_2" + }, + { + "game_id": 1710, + "examine": "A dragonstone amulet with 3 magic charges.", + "suffix": "charged_3" + }, + { + "game_id": 1712, + "examine": "A dragonstone amulet with 4 magic charges.", + "suffix": "charged_4" + } + ] + } } diff --git a/data/config/items/equipment/halberd.json b/data/config/items/equipment/halberd.json index 2417f8534..110a45013 100644 --- a/data/config/items/equipment/halberd.json +++ b/data/config/items/equipment/halberd.json @@ -31,7 +31,6 @@ "style": "halberd" } } - }, "rs:steel_halberd": { "game_id": 3194, @@ -261,8 +260,7 @@ }, "weapon_info": { "style": "halberd" - } - + } } } -} \ No newline at end of file +} diff --git a/data/config/items/equipment/slayer.json b/data/config/items/equipment/slayer.json index c3a5b6cec..17b31006b 100644 --- a/data/config/items/equipment/slayer.json +++ b/data/config/items/equipment/slayer.json @@ -1,433 +1,433 @@ { - "rs:black_mask": { - "game_id": 8921, - "examine": "An inert-seeming cave horror mask.", - "tradable": true, - "weight": 10, - "equippable": true, - "equipment_data": { - "equipment_slot": "head", - "requirements": { - "skills": { - "defence": 10, - "strength": 20, - "combat": 40 - } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": -3, - "ranged": -1 - }, - "defensive_bonuses": { - "stab": 9, - "slash": 10, - "crush": 8, - "magic": -1, - "ranged": 9 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 0, - "magic": 0 - } + "rs:black_mask": { + "game_id": 8921, + "examine": "An inert-seeming cave horror mask.", + "tradable": true, + "weight": 10, + "equippable": true, + "equipment_data": { + "equipment_slot": "head", + "requirements": { + "skills": { + "defence": 10, + "strength": 20, + "combat": 40 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": -3, + "ranged": -1 + }, + "defensive_bonuses": { + "stab": 9, + "slash": 10, + "crush": 8, + "magic": -1, + "ranged": 9 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 0, + "magic": 0 + } + }, + "variations": [ + { + "game_id": 8919, + "suffix": "1" + }, + { + "game_id": 8917, + "suffix": "2" + }, + { + "game_id": 8915, + "suffix": "3" + }, + { + "game_id": 8913, + "suffix": "4" + }, + { + "game_id": 8911, + "suffix": "5" + }, + { + "game_id": 8909, + "suffix": "6" + }, + { + "game_id": 8907, + "suffix": "7" + }, + { + "game_id": 8905, + "suffix": "8" + }, + { + "game_id": 8903, + "suffix": "9" + }, + { + "game_id": 8901, + "suffix": "10" + } + ] }, - "variations": [ - { - "game_id": 8919, - "suffix": "1" - }, - { - "game_id": 8917, - "suffix": "2" - }, - { - "game_id": 8915, - "suffix": "3" - }, - { - "game_id": 8913, - "suffix": "4" - }, - { - "game_id": 8911, - "suffix": "5" - }, - { - "game_id": 8909, - "suffix": "6" - }, - { - "game_id": 8907, - "suffix": "7" - }, - { - "game_id": 8905, - "suffix": "8" - }, - { - "game_id": 8903, - "suffix": "9" - }, - { - "game_id": 8901, - "suffix": "10" - } - ] - }, - "rs:witchwood_icon": { - "game_id": 8923, - "examine": "A stick on a string... pure style.", - "tradable": false, - "weight": 0.007, - "equippable": true, - "equipment_data": { - "equipment_slot": "neck", - "requirements": { - "skills": { - "slayer": 35 + "rs:witchwood_icon": { + "game_id": 8923, + "examine": "A stick on a string... pure style.", + "tradable": false, + "weight": 0.007, + "equippable": true, + "equipment_data": { + "equipment_slot": "neck", + "requirements": { + "skills": { + "slayer": 35 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 1, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 1, + "strength": 0, + "ranged": 0, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 1, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 1, - "strength": 0, - "ranged": 0, - "magic": 0 - } - } - }, - "rs:slayer_staff": { - "game_id": 4170, - "examine": "An old and magical staff.", - "tradable": true, - "weight": 1.814, - "equippable": true, - "equipment_data": { - "equipment_slot": "main_hand", - "requirements": { - "skills": { - "slayer": 55, - "magic": 50 + }, + "rs:slayer_staff": { + "game_id": 4170, + "examine": "An old and magical staff.", + "tradable": true, + "weight": 1.814, + "equippable": true, + "equipment_data": { + "equipment_slot": "main_hand", + "requirements": { + "skills": { + "slayer": 55, + "magic": 50 + } + }, + "offensive_bonuses": { + "speed": 4, + "stab": 7, + "slash": -1, + "crush": 25, + "magic": 12, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 2, + "slash": 3, + "crush": 1, + "magic": 10, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 35, + "ranged": 0, + "magic": 0 + }, + "weapon_info": { + "style": "magical_staff" + } } - }, - "offensive_bonuses": { - "speed": 4, - "stab": 7, - "slash": -1, - "crush": 25, - "magic": 12, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 2, - "slash": 3, - "crush": 1, - "magic": 10, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 35, - "ranged": 0, - "magic": 0 - }, - "weapon_info": { - "style": "magical_staff" - } - } - }, - "rs:nose_peg": { - "game_id": 4168, - "examine": "Protects me from any bad smells.", - "tradable": true, - "weight": 0.001, - "equippable": true, - "equipment_data": { - "equipment_slot": "head", - "requirements": { - "skills": { - "slayer": 60 + }, + "rs:nose_peg": { + "game_id": 4168, + "examine": "Protects me from any bad smells.", + "tradable": true, + "weight": 0.001, + "equippable": true, + "equipment_data": { + "equipment_slot": "head", + "requirements": { + "skills": { + "slayer": 60 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 0, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 0, - "magic": 0 - } - } - }, - "rs:ear_muffs": { - "game_id": 4166, - "examine": "These will protect my ears from loud noise.", - "tradable": true, - "weight": 0.113, - "equippable": true, - "equipment_data": { - "equipment_slot": "head", - "requirements": { - "skills": { - "slayer": 15 + }, + "rs:ear_muffs": { + "game_id": 4166, + "examine": "These will protect my ears from loud noise.", + "tradable": true, + "weight": 0.113, + "equippable": true, + "equipment_data": { + "equipment_slot": "head", + "requirements": { + "skills": { + "slayer": 15 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 0, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 0, - "magic": 0 - } - } - }, - "rs:face_mask": { - "game_id": 4164, - "examine": "Stops me breathing in too much dust.", - "tradable": true, - "weight": 0.113, - "equippable": true, - "equipment_data": { - "equipment_slot": "head", - "requirements": { - "skills": { - "slayer": 10 + }, + "rs:face_mask": { + "game_id": 4164, + "examine": "Stops me breathing in too much dust.", + "tradable": true, + "weight": 0.113, + "equippable": true, + "equipment_data": { + "equipment_slot": "head", + "requirements": { + "skills": { + "slayer": 10 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 0, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 0, - "magic": 0 - } - } - }, - "rs:rock_hammer": { - "game_id": 4162, - "examine": "I can even smash stone with this.", - "tradable": true, - "weight": 2.267, - "equippable": false - }, - "rs:bag_of_salt": { - "game_id": 4161, - "examine": "A bag of salt.", - "tradable": true, - "weight": 0, - "equippable": false - }, - "rs:broad_arrows": { - "game_id": 4160, - "examine": "Arrows with a wider than normal tip.", - "tradable": false, - "weight": 0, - "equippable": true, - "equipment_data": { - "equipment_slot": "quiver", - "requirements": { - "skills": { - "slayer": 55, - "ranged": 50 + }, + "rs:rock_hammer": { + "game_id": 4162, + "examine": "I can even smash stone with this.", + "tradable": true, + "weight": 2.267, + "equippable": false + }, + "rs:bag_of_salt": { + "game_id": 4161, + "examine": "A bag of salt.", + "tradable": true, + "weight": 0, + "equippable": false + }, + "rs:broad_arrows": { + "game_id": 4160, + "examine": "Arrows with a wider than normal tip.", + "tradable": false, + "weight": 0, + "equippable": true, + "equipment_data": { + "equipment_slot": "quiver", + "requirements": { + "skills": { + "slayer": 55, + "ranged": 50 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 28, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 28, - "magic": 0 - } - } - }, - "rs:leaf_bladed_spear": { - "game_id": 4158, - "examine": "A spear with a leaf-shaped point.", - "tradable": false, - "weight": 2.267, - "equippable": true, - "equipment_data": { - "equipment_slot": "2h", - "requirements": { - "skills": { - "slayer": 55, - "attack": 50 + }, + "rs:leaf_bladed_spear": { + "game_id": 4158, + "examine": "A spear with a leaf-shaped point.", + "tradable": false, + "weight": 2.267, + "equippable": true, + "equipment_data": { + "equipment_slot": "2h", + "requirements": { + "skills": { + "slayer": 55, + "attack": 50 + } + }, + "offensive_bonuses": { + "speed": 5, + "stab": 47, + "slash": 42, + "crush": 36, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 1, + "slash": 1, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 50, + "ranged": 0, + "magic": 0 + }, + "weapon_info": { + "style": "spear" + } } - }, - "offensive_bonuses": { - "speed": 5, - "stab": 47, - "slash": 42, - "crush": 36, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 1, - "slash": 1, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 50, - "ranged": 0, - "magic": 0 - }, - "weapon_info": { - "style": "spear" - } - } - }, - "rs:mirror_shield": { - "game_id": 4156, - "examine": "I can just about see things in this shield's reflection.", - "tradable": true, - "weight": 2.267, - "equippable": true, - "equipment_data": { - "equipment_slot": "off_hand", - "requirements": { - "skills": { - "slayer": 25, - "defence": 20 + }, + "rs:mirror_shield": { + "game_id": 4156, + "examine": "I can just about see things in this shield's reflection.", + "tradable": true, + "weight": 2.267, + "equippable": true, + "equipment_data": { + "equipment_slot": "off_hand", + "requirements": { + "skills": { + "slayer": 25, + "defence": 20 + } + }, + "offensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 10, + "slash": 15, + "crush": 5, + "magic": 5, + "ranged": 10 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 0, + "ranged": 0, + "magic": 0 + } } - }, - "offensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 10, - "slash": 15, - "crush": 5, - "magic": 5, - "ranged": 10 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 0, - "ranged": 0, - "magic": 0 - } - } - }, - "rs:enchanted_gem": { - "game_id": 4155, - "examine": "I can contact the Slayer Masters with this.", - "tradable": false, - "weight": 0.002, - "equippable": false - }, - "rs:granite_maul": { - "game_id": 4153, - "examine": "Simplicity is the best weapon.", - "tradable": true, - "weight": 4.535, - "equippable": true, - "equipment_data": { - "equipment_slot": "2h", - "requirements": { - "skills": { - "attack": 50 + }, + "rs:enchanted_gem": { + "game_id": 4155, + "examine": "I can contact the Slayer Masters with this.", + "tradable": false, + "weight": 0.002, + "equippable": false + }, + "rs:granite_maul": { + "game_id": 4153, + "examine": "Simplicity is the best weapon.", + "tradable": true, + "weight": 4.535, + "equippable": true, + "equipment_data": { + "equipment_slot": "2h", + "requirements": { + "skills": { + "attack": 50 + } + }, + "offensive_bonuses": { + "speed": 7, + "stab": 0, + "slash": 0, + "crush": 81, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 79, + "ranged": 0, + "magic": 0 + }, + "weapon_info": { + "style": "hammer" + } } - }, - "offensive_bonuses": { - "speed": 7, - "stab": 0, - "slash": 0, - "crush": 81, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 79, - "ranged": 0, - "magic": 0 - }, - "weapon_info": { - "style": "hammer" - } } - } } diff --git a/data/config/items/equipment/spears.json b/data/config/items/equipment/spears.json index 4ab6ce3b3..6fb7ac9b9 100644 --- a/data/config/items/equipment/spears.json +++ b/data/config/items/equipment/spears.json @@ -1,9 +1,9 @@ { - "rs:guthans_warspear": { - "game_id": 4726, - "tradable": true, - "notable": true, - "stackable": false, - "equippable": true - } + "rs:guthans_warspear": { + "game_id": 4726, + "tradable": true, + "notable": true, + "stackable": false, + "equippable": true + } } diff --git a/data/config/items/equipment/standard-metals/rune-armour.json b/data/config/items/equipment/standard-metals/rune-armour.json index 64af7772f..8382f5f15 100644 --- a/data/config/items/equipment/standard-metals/rune-armour.json +++ b/data/config/items/equipment/standard-metals/rune-armour.json @@ -256,7 +256,7 @@ "ranged": 80 }, "requirements": { - "quests" : { + "quests": { "rs:dragon_slayer": "complete" } } diff --git a/data/config/items/equipment/standard-metals/rune-god-armour.json b/data/config/items/equipment/standard-metals/rune-god-armour.json index ac0d7e051..19a9db5f4 100644 --- a/data/config/items/equipment/standard-metals/rune-god-armour.json +++ b/data/config/items/equipment/standard-metals/rune-god-armour.json @@ -119,7 +119,7 @@ "ranged": 80 }, "requirements": { - "quests" : { + "quests": { "rs:dragon_slayer": "complete" } } @@ -229,7 +229,7 @@ "ranged": 80 }, "requirements": { - "quests" : { + "quests": { "rs:dragon_slayer": "complete" } } @@ -339,7 +339,7 @@ "ranged": 80 }, "requirements": { - "quests" : { + "quests": { "rs:dragon_slayer": "complete" } } diff --git a/data/config/items/equipment/standard-metals/white-armour.json b/data/config/items/equipment/standard-metals/white-armour.json index 5de34f004..49ae9aa4a 100644 --- a/data/config/items/equipment/standard-metals/white-armour.json +++ b/data/config/items/equipment/standard-metals/white-armour.json @@ -28,4 +28,4 @@ } } } -} \ No newline at end of file +} diff --git a/data/config/items/equipment/whips.json b/data/config/items/equipment/whips.json index 16662cd0e..11e5d285d 100644 --- a/data/config/items/equipment/whips.json +++ b/data/config/items/equipment/whips.json @@ -1,80 +1,80 @@ { - "rs:abyssal_whip": { - "game_id": 4151, - "examine": "A weapon from the Abyss.", - "tradable": true, - "weight": 0.453, - "equippable": true, - "equipment_data": { - "equipment_slot": "main_hand", - "requirements": { - "skills": { - "attack": 70 + "rs:abyssal_whip": { + "game_id": 4151, + "examine": "A weapon from the Abyss.", + "tradable": true, + "weight": 0.453, + "equippable": true, + "equipment_data": { + "equipment_slot": "main_hand", + "requirements": { + "skills": { + "attack": 70 + } + }, + "offensive_bonuses": { + "speed": 4, + "stab": 0, + "slash": 82, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 0, + "strength": 82, + "ranged": 0, + "magic": 0 + }, + "weapon_info": { + "style": "whip" + } } - }, - "offensive_bonuses": { - "speed": 4, - "stab": 0, - "slash": 82, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 0, - "strength": 82, - "ranged": 0, - "magic": 0 - }, - "weapon_info": { - "style": "whip" - } - } - }, - "rs:veracs_flail": { - "game_id": 4755, - "examine": "Verac the Defiled's flail.", - "tradable": true, - "weight": 2.267, - "equippable": true, - "equipment_data": { - "equipment_slot": "2h", - "requirements": { - "skills": { - "attack": 70 + }, + "rs:veracs_flail": { + "game_id": 4755, + "examine": "Verac the Defiled's flail.", + "tradable": true, + "weight": 2.267, + "equippable": true, + "equipment_data": { + "equipment_slot": "2h", + "requirements": { + "skills": { + "attack": 70 + } + }, + "offensive_bonuses": { + "speed": 5, + "stab": 68, + "slash": -2, + "crush": 82, + "magic": 0, + "ranged": 0 + }, + "defensive_bonuses": { + "stab": 0, + "slash": 0, + "crush": 0, + "magic": 0, + "ranged": 0 + }, + "skill_bonuses": { + "prayer": 6, + "strength": 72, + "ranged": 0, + "magic": 0 + }, + "weapon_info": { + "style": "mace" + } } - }, - "offensive_bonuses": { - "speed": 5, - "stab": 68, - "slash": -2, - "crush": 82, - "magic": 0, - "ranged": 0 - }, - "defensive_bonuses": { - "stab": 0, - "slash": 0, - "crush": 0, - "magic": 0, - "ranged": 0 - }, - "skill_bonuses": { - "prayer": 6, - "strength": 72, - "ranged": 0, - "magic": 0 - }, - "weapon_info": { - "style": "mace" - } } - } } diff --git a/data/config/items/food.json b/data/config/items/food.json index 9fa458065..fea7181b0 100644 --- a/data/config/items/food.json +++ b/data/config/items/food.json @@ -4,7 +4,7 @@ "tradable": true, "consumable": true, "metadata": { - "consume_effects":{ + "consume_effects": { "clock": "food" }, "special": false @@ -14,7 +14,7 @@ "tradable": true, "consumable": true, "metadata": { - "consume_effects":{ + "consume_effects": { "clock": "food" }, "special": false @@ -127,7 +127,7 @@ "metadata": { "consume_effects": { "skills": { - "hitpoints": [5,7] + "hitpoints": [5, 7] } } } @@ -149,7 +149,7 @@ "metadata": { "consume_effects": { "skills": { - "hitpoints": [5,8] + "hitpoints": [5, 8] } } } @@ -226,7 +226,7 @@ "metadata": { "consume_effects": { "skills": { - "hitpoints": [8,12] + "hitpoints": [8, 12] } } } @@ -504,26 +504,26 @@ } }, "variations": [ - { - "metadata": { - "consume_effects": { - "replaced_by": "rs:admiral_pie:1" - } - }, - "suffix": "0", - "game_id": 7198 + { + "metadata": { + "consume_effects": { + "replaced_by": "rs:admiral_pie:1" + } }, - { - "metadata": { - "consume_effects": { - "replaced_by": "rs:pie_dish" - } - }, - "suffix": "1", - "tradable": false, - "game_id": 7200 - } - ] + "suffix": "0", + "game_id": 7198 + }, + { + "metadata": { + "consume_effects": { + "replaced_by": "rs:pie_dish" + } + }, + "suffix": "1", + "tradable": false, + "game_id": 7200 + } + ] }, "rs:wild_pie": { "extends": "rs:food", @@ -1119,7 +1119,6 @@ "rs:butter": { "tradable": true, "game_id": 6697 - }, "rs:raw_shrimp": { "extends": "rs:food", diff --git a/data/config/items/holiday/partyhats.json b/data/config/items/holiday/partyhats.json index 28247081f..42717d7ee 100644 --- a/data/config/items/holiday/partyhats.json +++ b/data/config/items/holiday/partyhats.json @@ -35,4 +35,4 @@ "extends": "rs:partyhat", "game_id": 1048 } -} \ No newline at end of file +} diff --git a/data/config/items/logs.json b/data/config/items/logs.json index 242b814df..6a3a63733 100644 --- a/data/config/items/logs.json +++ b/data/config/items/logs.json @@ -75,10 +75,10 @@ "game_id": 1513 }, "rs:bark": { - "game_id": 3239, - "examine": "Bark from a hollow tree.", - "tradable": true, - "weight": 1, - "equippable": false + "game_id": 3239, + "examine": "Bark from a hollow tree.", + "tradable": true, + "weight": 1, + "equippable": false } } diff --git a/data/config/items/quests/lost-city.json b/data/config/items/quests/lost-city.json index 496cf1f0c..e3b2d928b 100644 --- a/data/config/items/quests/lost-city.json +++ b/data/config/items/quests/lost-city.json @@ -1,9 +1,9 @@ { - "rs:dramen_branch": { - "game_id": 771, - "examine": "A limb of the fabled Dramen tree.", - "tradable": false, - "weight": 2.267, - "equippable": false - } + "rs:dramen_branch": { + "game_id": 771, + "examine": "A limb of the fabled Dramen tree.", + "tradable": false, + "weight": 2.267, + "equippable": false + } } diff --git a/data/config/items/skills/herblore.json b/data/config/items/skills/herblore.json index a68c6a9d7..fe0c80585 100644 --- a/data/config/items/skills/herblore.json +++ b/data/config/items/skills/herblore.json @@ -140,7 +140,4 @@ "rs:torstol": { "game_id": 269 } - } - - diff --git a/data/config/items/skills/herblore/herbs.json b/data/config/items/skills/herblore/herbs.json index a4a74c866..7104e6d1d 100644 --- a/data/config/items/skills/herblore/herbs.json +++ b/data/config/items/skills/herblore/herbs.json @@ -1,125 +1,125 @@ { - "presets": { - "rs:grimy_herb_base": { - "examine": "It needs cleaning.", - "weight": 0.007, - "tradable": true - }, - "rs:clean_herb_base": { - "weight": 0.007, - "tradable": true + "presets": { + "rs:grimy_herb_base": { + "examine": "It needs cleaning.", + "weight": 0.007, + "tradable": true + }, + "rs:clean_herb_base": { + "weight": 0.007, + "tradable": true + } + }, + "rs:grimy_guam": { + "extends": "rs:grimy_herb_base", + "game_id": 199 + }, + "rs:grimy_marrentill": { + "extends": "rs:grimy_herb_base", + "game_id": 201 + }, + "rs:grimy_tarromin": { + "extends": "rs:grimy_herb_base", + "game_id": 203 + }, + "rs:grimy_harralander": { + "extends": "rs:grimy_herb_base", + "game_id": 205 + }, + "rs:grimy_ranarr": { + "extends": "rs:grimy_herb_base", + "game_id": 207 + }, + "rs:grimy_irit": { + "extends": "rs:grimy_herb_base", + "game_id": 209 + }, + "rs:grimy_avantoe": { + "extends": "rs:grimy_herb_base", + "game_id": 211 + }, + "rs:grimy_kwuarm": { + "extends": "rs:grimy_herb_base", + "game_id": 213 + }, + "rs:grimy_cadantine": { + "extends": "rs:grimy_herb_base", + "game_id": 215 + }, + "rs:grimy_dwarf_weed": { + "extends": "rs:grimy_herb_base", + "game_id": 217 + }, + "rs:grimy_torstol": { + "extends": "rs:grimy_herb_base", + "game_id": 219 + }, + "rs:grimy_toadflax": { + "extends": "rs:grimy_herb_base", + "game_id": 3049 + }, + "rs:grimy_snapdragon": { + "extends": "rs:grimy_herb_base", + "game_id": 3051 + }, + "rs:grimy_lantadyme": { + "extends": "rs:grimy_herb_base", + "game_id": 2485 + }, + "rs:herb_guam": { + "extends": "rs:clean_herb_base", + "game_id": 249 + }, + "rs:herb_marrentill": { + "extends": "rs:clean_herb_base", + "game_id": 251 + }, + "rs:herb_tarromin": { + "extends": "rs:clean_herb_base", + "game_id": 253 + }, + "rs:herb_harralander": { + "extends": "rs:clean_herb_base", + "game_id": 255 + }, + "rs:herb_ranarr": { + "extends": "rs:clean_herb_base", + "game_id": 257 + }, + "rs:herb_irit": { + "extends": "rs:clean_herb_base", + "game_id": 259 + }, + "rs:herb_avantoe": { + "extends": "rs:clean_herb_base", + "game_id": 261 + }, + "rs:herb_kwuarm": { + "extends": "rs:clean_herb_base", + "game_id": 263 + }, + "rs:herb_cadantine": { + "extends": "rs:clean_herb_base", + "game_id": 265 + }, + "rs:herb_dwarf_weed": { + "extends": "rs:clean_herb_base", + "game_id": 267 + }, + "rs:herb_torstol": { + "extends": "rs:clean_herb_base", + "game_id": 269 + }, + "rs:herb_toadflax": { + "extends": "rs:clean_herb_base", + "game_id": 2998 + }, + "rs:herb_snapdragon": { + "extends": "rs:clean_herb_base", + "game_id": 3000 + }, + "rs:herb_lantadyme": { + "extends": "rs:clean_herb_base", + "game_id": 2481 } - }, - "rs:grimy_guam": { - "extends": "rs:grimy_herb_base", - "game_id": 199 - }, - "rs:grimy_marrentill": { - "extends": "rs:grimy_herb_base", - "game_id": 201 - }, - "rs:grimy_tarromin": { - "extends": "rs:grimy_herb_base", - "game_id": 203 - }, - "rs:grimy_harralander": { - "extends": "rs:grimy_herb_base", - "game_id": 205 - }, - "rs:grimy_ranarr": { - "extends": "rs:grimy_herb_base", - "game_id": 207 - }, - "rs:grimy_irit": { - "extends": "rs:grimy_herb_base", - "game_id": 209 - }, - "rs:grimy_avantoe": { - "extends": "rs:grimy_herb_base", - "game_id": 211 - }, - "rs:grimy_kwuarm": { - "extends": "rs:grimy_herb_base", - "game_id": 213 - }, - "rs:grimy_cadantine": { - "extends": "rs:grimy_herb_base", - "game_id": 215 - }, - "rs:grimy_dwarf_weed": { - "extends": "rs:grimy_herb_base", - "game_id": 217 - }, - "rs:grimy_torstol": { - "extends": "rs:grimy_herb_base", - "game_id": 219 - }, - "rs:grimy_toadflax": { - "extends": "rs:grimy_herb_base", - "game_id": 3049 - }, - "rs:grimy_snapdragon": { - "extends": "rs:grimy_herb_base", - "game_id": 3051 - }, - "rs:grimy_lantadyme": { - "extends": "rs:grimy_herb_base", - "game_id": 2485 - }, - "rs:herb_guam": { - "extends": "rs:clean_herb_base", - "game_id": 249 - }, - "rs:herb_marrentill": { - "extends": "rs:clean_herb_base", - "game_id": 251 - }, - "rs:herb_tarromin": { - "extends": "rs:clean_herb_base", - "game_id": 253 - }, - "rs:herb_harralander": { - "extends": "rs:clean_herb_base", - "game_id": 255 - }, - "rs:herb_ranarr": { - "extends": "rs:clean_herb_base", - "game_id": 257 - }, - "rs:herb_irit": { - "extends": "rs:clean_herb_base", - "game_id": 259 - }, - "rs:herb_avantoe": { - "extends": "rs:clean_herb_base", - "game_id": 261 - }, - "rs:herb_kwuarm": { - "extends": "rs:clean_herb_base", - "game_id": 263 - }, - "rs:herb_cadantine": { - "extends": "rs:clean_herb_base", - "game_id": 265 - }, - "rs:herb_dwarf_weed": { - "extends": "rs:clean_herb_base", - "game_id": 267 - }, - "rs:herb_torstol": { - "extends": "rs:clean_herb_base", - "game_id": 269 - }, - "rs:herb_toadflax": { - "extends": "rs:clean_herb_base", - "game_id": 2998 - }, - "rs:herb_snapdragon": { - "extends": "rs:clean_herb_base", - "game_id": 3000 - }, - "rs:herb_lantadyme": { - "extends": "rs:clean_herb_base", - "game_id": 2481 - } } diff --git a/data/config/items/skills/herblore/tools.json b/data/config/items/skills/herblore/tools.json index 4fae1e8f7..832a89c73 100644 --- a/data/config/items/skills/herblore/tools.json +++ b/data/config/items/skills/herblore/tools.json @@ -1,8 +1,8 @@ { - "rs:pestle_and_mortar" : { - "game_id": 233, - "examine": "I can grind things for potions in this.", - "tradable": true, - "weight": 0.056 - } + "rs:pestle_and_mortar": { + "game_id": 233, + "examine": "I can grind things for potions in this.", + "tradable": true, + "weight": 0.056 + } } diff --git a/data/config/items/skills/mining.json b/data/config/items/skills/mining.json index afccc0a75..ad8062e8f 100644 --- a/data/config/items/skills/mining.json +++ b/data/config/items/skills/mining.json @@ -55,7 +55,7 @@ "weight": 2.267, "equippable": false }, - "rs:coal":{ + "rs:coal": { "game_id": 453, "examine": "Hmm a non-renewable energy source!", "tradable": true, @@ -83,7 +83,7 @@ "weight": 2.721, "equippable": false }, - "rs:soft_clay":{ + "rs:soft_clay": { "game_id": 1761, "examine": "Clay soft enough to mould.", "tradable": true, diff --git a/data/config/items/skills/prayer.json b/data/config/items/skills/prayer.json index 67c875313..ed7d1e078 100644 --- a/data/config/items/skills/prayer.json +++ b/data/config/items/skills/prayer.json @@ -5,5 +5,4 @@ "rs:herblore_anti_poison_potion": { "game_id": 235 } - -} \ No newline at end of file +} diff --git a/data/config/items/skills/runecrafting.json b/data/config/items/skills/runecrafting.json index 8926a2513..eb9de918d 100644 --- a/data/config/items/skills/runecrafting.json +++ b/data/config/items/skills/runecrafting.json @@ -259,7 +259,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of air.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -270,7 +270,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of the body.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -281,7 +281,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of chaos.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -292,7 +292,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of the cosmos.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -303,7 +303,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of death.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -314,7 +314,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of the earth.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -325,7 +325,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of fire.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -336,7 +336,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of law.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -347,7 +347,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of the mind.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -358,7 +358,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of nature.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -369,7 +369,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of water.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -380,7 +380,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of blood.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" @@ -391,7 +391,7 @@ "tradable": true, "stackable": false, "examine": "A tiara infused with the properties of the soul.", - "weight": 1.000, + "weight": 1.0, "equippable": true, "equipment_data": { "equipment_slot": "head" diff --git a/data/config/music/musicRegions.json b/data/config/music/musicRegions.json index aab659f8f..06104d102 100644 --- a/data/config/music/musicRegions.json +++ b/data/config/music/musicRegions.json @@ -1,3585 +1,2542 @@ { - "musicRegions": [ - { - "songId": 363, - "songName": "7th Realm", - "musicTabButtonId": 299, - "regionIds": [ - 10645, - 10644 - ] - }, - { - "songId": 177, - "songName": "Adventure", - "musicTabButtonId": 25, - "regionIds": [ - 12854 - ] - }, - { - "songId": 50, - "songName": "Al-Kharid", - "musicTabButtonId": 26, - "regionIds": [ - 13105, - 13361 - ] - }, - { - "songId": 73, - "songName": "All's Fairy In Love'N'War", - "musicTabButtonId": 443, - "regionIds": [ - 0 - ] - }, - { - "songId": 102, - "songName": "Alone", - "musicTabButtonId": 27, - "regionIds": [ - 12086, - 10390, - 10134 - ] - }, - { - "songId": 90, - "songName": "Ambient Jungle", - "musicTabButtonId": 28, - "regionIds": [ - 11310 - ] - }, - { - "songId": 305, - "songName": "Anywhere", - "musicTabButtonId": 276, - "regionIds": [ - 10795 - ] - }, - { - "songId": 123, - "songName": "Arabian 2", - "musicTabButtonId": 30, - "regionIds": [ - 13107 - ] - }, - { - "songId": 124, - "songName": "Arabian 3", - "musicTabButtonId": 31, - "regionIds": [ - 12848 - ] - }, - { - "songId": 36, - "songName": "Arabian", - "musicTabButtonId": 29, - "regionIds": [ - 13617, - 13106 - ] - }, - { - "songId": 19, - "songName": "Arabique", - "musicTabButtonId": 32, - "regionIds": [ - 11417 - ] - }, - { - "songId": 160, - "songName": "Army of Darkness", - "musicTabButtonId": 33, - "regionIds": [ - 12088 - ] - }, - { - "songId": 186, - "songName": "Arrival", - "musicTabButtonId": 34, - "regionIds": [ - 11572 - ] - }, - { - "songId": 247, - "songName": "Artistry", - "musicTabButtonId": 245, - "regionIds": [ - 8010 - ] - }, - { - "songId": 24, - "songName": "Attack 1", - "musicTabButtonId": 35, - "regionIds": [ - 10034 - ] - }, - { - "songId": 25, - "songName": "Attack 2", - "musicTabButtonId": 36, - "regionIds": [ - 11414 - ] - }, - { - "songId": 26, - "songName": "Attack 3", - "musicTabButtonId": 37, - "regionIds": [ - 0 - ] - }, - { - "songId": 27, - "songName": "Attack 4", - "musicTabButtonId": 38, - "regionIds": [ - 10289 - ] - }, - { - "songId": 28, - "songName": "Attack 5", - "musicTabButtonId": 39, - "regionIds": [ - 9033 - ] - }, - { - "songId": 29, - "songName": "Attack 6", - "musicTabButtonId": 40, - "regionIds": [ - 10387 - ] - }, - { - "songId": 180, - "songName": "Attention", - "musicTabButtonId": 41, - "regionIds": [ - 11825 - ] - }, - { - "songId": 2, - "songName": "Autumn Voyage", - "musicTabButtonId": 42, - "regionIds": [ - 12851 - ] - }, - { - "songId": 497, - "songName": "Aye Car Rum Ba", - "musicTabButtonId": 373, - "regionIds": [ - 8527 - ] - }, - { - "songId": 248, - "songName": "Aztec", - "musicTabButtonId": 217, - "regionIds": [ - 11157, - 11158, - 11156, - 10902 - ] - }, - { - "songId": 324, - "songName": "Background", - "musicTabButtonId": 43, - "regionIds": [ - 11060, - 11316, - 7758 - ] - }, - { - "songId": 152, - "songName": "Ballad of Enchantment", - "musicTabButtonId": 44, - "regionIds": [ - 10290 - ] - }, - { - "songId": 263, - "songName": "Bandit Camp", - "musicTabButtonId": 243, - "regionIds": [ - 12590 - ] - }, - { - "songId": 141, - "songName": "Barbarianism", - "musicTabButtonId": 253, - "regionIds": [ - 12341, - 12441 - ] - }, - { - "songId": 345, - "songName": "Barking Mad", - "musicTabButtonId": 305, - "regionIds": [ - 14234 - ] - }, - { - "songId": 99, - "songName": "Baroque", - "musicTabButtonId": 45, - "regionIds": [ - 10547 - ] - }, - { - "songId": 100, - "songName": "Beyond", - "musicTabButtonId": 46, - "regionIds": [ - 11675, - 11419, - 11418 - ] - }, - { - "songId": 83, - "songName": "Big Chords", - "musicTabButtonId": 47, - "regionIds": [ - 10032, - 11593 - ] - }, - { - "songId": 498, - "songName": "Blistering Barnacles", - "musicTabButtonId": 372, - "regionIds": [ - 8528 - ] - }, - { - "songId": 342, - "songName": "Body Parts", - "musicTabButtonId": 304, - "regionIds": [ - 13979, - 14235 - ] - }, - { - "songId": 154, - "songName": "Bone Dance", - "musicTabButtonId": 248, - "regionIds": [ - 13619 - ] - }, - { - "songId": 266, - "songName": "Bone Dry", - "musicTabButtonId": 322, - "regionIds": [ - 12946, - 13202 - ] - }, - { - "songId": 64, - "songName": "Book of Spells", - "musicTabButtonId": 48, - "regionIds": [ - 12593 - ] - }, - { - "songId": 291, - "songName": "Borderland", - "musicTabButtonId": 258, - "regionIds": [ - 10809, - 10810 - ] - }, - { - "songId": 132, - "songName": "Breeze", - "musicTabButtonId": 229, - "regionIds": [ - 9010 - ] - }, - { - "songId": 471, - "songName": "Brew Hoo Hoo", - "musicTabButtonId": 357, - "regionIds": [ - 14747 - ] - }, - { - "songId": 194, - "songName": "Brimstail's Scales", - "musicTabButtonId": 451, - "regionIds": [ - 9625 - ] - }, - { - "songId": 489, - "songName": "Bubble And Squeak", - "musicTabButtonId": 380, - "regionIds": [ - 7753 - ] - }, - { - "songId": 545, - "songName": "Cabin Fever", - "musicTabButtonId": 400, - "regionIds": [ - 0 - ] - }, - { - "songId": 104, - "songName": "Camelot", - "musicTabButtonId": 49, - "regionIds": [ - 11062, - 11063 - ] - }, - { - "songId": 314, - "songName": "Castlewars", - "musicTabButtonId": 285, - "regionIds": [ - 9520, - 9620 - ] - }, - { - "songId": 481, - "songName": "Catch Me If You Can", - "musicTabButtonId": 379, - "regionIds": [ - 10646 - ] - }, - { - "songId": 325, - "songName": "Cave Background", - "musicTabButtonId": 50, - "regionIds": [ - 12185, - 11929, - 12184 - ] - }, - { - "songId": 357, - "songName": "Cave of Beasts", - "musicTabButtonId": 311, - "regionIds": [ - 11165 - ] - }, - { - "songId": 389, - "songName": "Cave of The Goblins", - "musicTabButtonId": 313, - "regionIds": [ - 12949, - 12693 - ] - }, - { - "songId": 68, - "songName": "Cavern", - "musicTabButtonId": 51, - "regionIds": [ - 10388, - 10389, - 12193 - ] - }, - { - "songId": 330, - "songName": "Cellar Song", - "musicTabButtonId": 197, - "regionIds": [ - 12697 - ] - }, - { - "songId": 63, - "songName": "Chain of Command", - "musicTabButtonId": 52, - "regionIds": [ - 10905, - 10651, - 10648, - 10649, - 10650 - ] - }, - { - "songId": 282, - "songName": "Chamber", - "musicTabButtonId": 291, - "regionIds": [ - 11078, - 10821 - ] - }, - { - "songId": 583, - "songName": "Chef Surprise", - "musicTabButtonId": 406, - "regionIds": [ - 0 - ] - }, - { - "songId": 575, - "songName": "Chickened Out", - "musicTabButtonId": 405, - "regionIds": [ - 9796 - ] - }, - { - "songId": 71, - "songName": "Chompy Hunt", - "musicTabButtonId": 202, - "regionIds": [ - 10542, - 10642 - ] - }, - { - "songId": 383, - "songName": "City of The Dead", - "musicTabButtonId": 327, - "regionIds": [ - 12844, - 12843, - 13099 - ] - }, - { - "songId": 373, - "songName": "Claustrophobia", - "musicTabButtonId": 316, - "regionIds": [ - 9549, - 9293 - ] - }, - { - "songId": 67, - "songName": "Close Quarters", - "musicTabButtonId": 199, - "regionIds": [ - 12602 - ] - }, - { - "songId": 269, - "songName": "Competition", - "musicTabButtonId": 254, - "regionIds": [ - 8781 - ] - }, - { - "songId": 142, - "songName": "Complication", - "musicTabButtonId": 270, - "regionIds": [ - 9035 - ] - }, - { - "songId": 258, - "songName": "Contest", - "musicTabButtonId": 222, - "regionIds": [ - 11576 - ] - }, - { - "songId": 418, - "songName": "Corporal Punishment", - "musicTabButtonId": 370, - "regionIds": [ - 12619 - ] - }, - { - "songId": 509, - "songName": "Corridors of Power", - "musicTabButtonId": 423, - "regionIds": [ - 0 - ] - }, - { - "songId": 178, - "songName": "Courage", - "musicTabButtonId": 256, - "regionIds": [ - 11673, - 11674 - ] - }, - { - "songId": 259, - "songName": "Crystal Castle", - "musicTabButtonId": 231, - "regionIds": [ - 9011, - 9012 - ] - }, - { - "songId": 181, - "songName": "Crystal Cave", - "musicTabButtonId": 53, - "regionIds": [ - 9797 - ] - }, - { - "songId": 169, - "songName": "Crystal Sword", - "musicTabButtonId": 54, - "regionIds": [ - 12855, - 10647 - ] - }, - { - "songId": 59, - "songName": "Cursed", - "musicTabButtonId": 205, - "regionIds": [ - 9879, - 9623 - ] - }, - { - "songId": 198, - "songName": "Dagannoth Dawn", - "musicTabButtonId": 374, - "regionIds": [ - 7748, - 7236 - ] - }, - { - "songId": 560, - "songName": "Dance of Death", - "musicTabButtonId": 436, - "regionIds": [ - 0 - ] - }, - { - "songId": 380, - "songName": "Dance of The Undead", - "musicTabButtonId": 334, - "regionIds": [ - 14131 - ] - }, - { - "songId": 336, - "songName": "Dangerous Road", - "musicTabButtonId": 264, - "regionIds": [ - 11413 - ] - }, - { - "songId": 381, - "songName": "Dangerous Way", - "musicTabButtonId": 335, - "regionIds": [ - 14231 - ] - }, - { - "songId": 182, - "songName": "Dangerous", - "musicTabButtonId": 55, - "regionIds": [ - 12343, - 13115, - 13371 - ] - }, - { - "songId": 326, - "songName": "Dark", - "musicTabButtonId": 56, - "regionIds": [ - 13113, - 13369 - ] - }, - { - "songId": 576, - "songName": "Davy Jones Locker", - "musicTabButtonId": 404, - "regionIds": [ - 11924 - ] - }, - { - "songId": 476, - "songName": "Dead Can Dance", - "musicTabButtonId": 359, - "regionIds": [ - 12601 - ] - }, - { - "songId": 84, - "songName": "Dead Quiet", - "musicTabButtonId": 216, - "regionIds": [ - 13621, - 9294, - 9550 - ] - }, - { - "songId": 288, - "songName": "Deadlands", - "musicTabButtonId": 246, - "regionIds": [ - 14134, - 14390 - ] - }, - { - "songId": 278, - "songName": "Deep Down", - "musicTabButtonId": 290, - "regionIds": [ - 11079, - 10822, - 10823 - ] - }, - { - "songId": 37, - "songName": "Deep Wildy", - "musicTabButtonId": 57, - "regionIds": [ - 11835, - 11836 - ] - }, - { - "songId": 465, - "songName": "Desert Heat", - "musicTabButtonId": 385, - "regionIds": [ - 13615, - 13614 - ] - }, - { - "songId": 174, - "songName": "Desert Voyage", - "musicTabButtonId": 58, - "regionIds": [ - 13103, - 13359, - 13102 - ] - }, - { - "songId": 532, - "songName": "Diango's Little Helpers", - "musicTabButtonId": 392, - "regionIds": [ - 8005 - ] - }, - { - "songId": 86, - "songName": "Dimension X", - "musicTabButtonId": 442, - "regionIds": [ - 0 - ] - }, - { - "songId": 501, - "songName": "Distant Land", - "musicTabButtonId": 409, - "regionIds": [ - 13874, - 14130, - 13873, - 14129 - ] - }, - { - "songId": 610, - "songName": "Distillery Hilarity", - "musicTabButtonId": 432, - "regionIds": [ - 0 - ] - }, - { - "songId": 537, - "songName": "Dogs of War", - "musicTabButtonId": 437, - "regionIds": [ - 0 - ] - }, - { - "songId": 56, - "songName": "Doorways", - "musicTabButtonId": 59, - "regionIds": [ - 12598 - ] - }, - { - "songId": 361, - "songName": "Down Below", - "musicTabButtonId": 326, - "regionIds": [ - 12439, - 12438 - ] - }, - { - "songId": 143, - "songName": "Down To Earth", - "musicTabButtonId": 255, - "regionIds": [ - 10571 - ] - }, - { - "songId": 358, - "songName": "Dragontooth Island", - "musicTabButtonId": 309, - "regionIds": [ - 15159 - ] - }, - { - "songId": 327, - "songName": "Dream", - "musicTabButtonId": 60, - "regionIds": [ - 12594 - ] - }, - { - "songId": 623, - "songName": "Dreamstate", - "musicTabButtonId": 446, - "regionIds": [ - 0 - ] - }, - { - "songId": 47, - "songName": "Duel Arena", - "musicTabButtonId": 189, - "regionIds": [ - 13362 - ] - }, - { - "songId": 173, - "songName": "Dunjun", - "musicTabButtonId": 61, - "regionIds": [ - 11928, - 11672 - ] - }, - { - "songId": 351, - "songName": "Dynasty", - "musicTabButtonId": 317, - "regionIds": [ - 13358 - ] - }, - { - "songId": 69, - "songName": "Egypt", - "musicTabButtonId": 62, - "regionIds": [ - 13104, - 13360 - ] - }, - { - "songId": 252, - "songName": "Elven Mist", - "musicTabButtonId": 239, - "regionIds": [ - 9266 - ] - }, - { - "songId": 148, - "songName": "Emotion", - "musicTabButtonId": 63, - "regionIds": [ - 10033, - 10133, - 10309, - 11081 - ] - }, - { - "songId": 138, - "songName": "Emperor", - "musicTabButtonId": 179, - "regionIds": [ - 11570, - 11670 - ] - }, - { - "songId": 17, - "songName": "Escape", - "musicTabButtonId": 198, - "regionIds": [ - 10903 - ] - }, - { - "songId": 285, - "songName": "Etceteria", - "musicTabButtonId": 273, - "regionIds": [ - 10300 - ] - }, - { - "songId": 586, - "songName": "Everlasting Fire", - "musicTabButtonId": 418, - "regionIds": [ - 13373 - ] - }, - { - "songId": 268, - "songName": "Everywhere", - "musicTabButtonId": 236, - "regionIds": [ - 8499, - 8755 - ] - }, - { - "songId": 411, - "songName": "Evil Bob's Island", - "musicTabButtonId": 358, - "regionIds": [ - 10058 - ] - }, - { - "songId": 106, - "songName": "Expanse", - "musicTabButtonId": 64, - "regionIds": [ - 12852, - 12605, - 12952 - ] - }, - { - "songId": 41, - "songName": "Expecting", - "musicTabButtonId": 65, - "regionIds": [ - 9522, - 9778, - 9878 - ] - }, - { - "songId": 153, - "songName": "Expedition", - "musicTabButtonId": 175, - "regionIds": [ - 11676, - 9619 - ] - }, - { - "songId": 270, - "songName": "Exposed", - "musicTabButtonId": 232, - "regionIds": [ - 8752 - ] - }, - { - "songId": 118, - "songName": "Faerie", - "musicTabButtonId": 66, - "regionIds": [ - 9541, - 9540 - ] - }, - { - "songId": 337, - "songName": "Faithless", - "musicTabButtonId": 265, - "regionIds": [ - 12856, - 13112 - ] - }, - { - "songId": 72, - "songName": "Fanfare", - "musicTabButtonId": 67, - "regionIds": [ - 11828 - ] - }, - { - "songId": 166, - "songName": "Fanfare2", - "musicTabButtonId": 68, - "regionIds": [ - 11823 - ] - }, - { - "songId": 167, - "songName": "Fanfare3", - "musicTabButtonId": 69, - "regionIds": [ - 10545 - ] - }, - { - "songId": 504, - "songName": "Fangs For The Memory", - "musicTabButtonId": 410, - "regionIds": [ - 0 - ] - }, - { - "songId": 372, - "songName": "Far Away", - "musicTabButtonId": 348, - "regionIds": [ - 9265 - ] - }, - { - "songId": 602, - "songName": "Fear And Loathing", - "musicTabButtonId": 411, - "regionIds": [ - 0 - ] - }, - { - "songId": 344, - "songName": "Fenkenstrain's Refrain", - "musicTabButtonId": 303, - "regionIds": [ - 13879, - 14135 - ] - }, - { - "songId": 375, - "songName": "Fight Or Flight", - "musicTabButtonId": 349, - "regionIds": [ - 8008, - 7752 - ] - }, - { - "songId": 312, - "songName": "Find My Way", - "musicTabButtonId": 284, - "regionIds": [ - 10894, - 11150 - ] - }, - { - "songId": 463, - "songName": "Fire And Brimstone", - "musicTabButtonId": 365, - "regionIds": [ - 9552 - ] - }, - { - "songId": 119, - "songName": "Fishing", - "musicTabButtonId": 70, - "regionIds": [ - 11317 - ] - }, - { - "songId": 163, - "songName": "Flute Salad", - "musicTabButtonId": 71, - "regionIds": [ - 12595 - ] - }, - { - "songId": 558, - "songName": "Food For Thought", - "musicTabButtonId": 438, - "regionIds": [ - 0 - ] - }, - { - "songId": 121, - "songName": "Forbidden", - "musicTabButtonId": 204, - "regionIds": [ - 13111, - 13367 - ] - }, - { - "songId": 251, - "songName": "Forest", - "musicTabButtonId": 238, - "regionIds": [ - 9009 - ] - }, - { - "songId": 98, - "songName": "Forever", - "musicTabButtonId": 72, - "regionIds": [ - 12342, - 12444, - 12443, - 12442 - ] - }, - { - "songId": 436, - "songName": "Forgettable Melody", - "musicTabButtonId": 350, - "regionIds": [ - 7501 - ] - }, - { - "songId": 378, - "songName": "Forgotten", - "musicTabButtonId": 320, - "regionIds": [ - 10828 - ] - }, - { - "songId": 409, - "songName": "Frogland", - "musicTabButtonId": 355, - "regionIds": [ - 9802 - ] - }, - { - "songId": 294, - "songName": "Frostbite", - "musicTabButtonId": 325, - "regionIds": [ - 11323, - 11579 - ] - }, - { - "songId": 347, - "songName": "Fruits De Mer", - "musicTabButtonId": 272, - "regionIds": [ - 11059 - ] - }, - { - "songId": 603, - "songName": "Funny Bunnies", - "musicTabButtonId": 415, - "regionIds": [ - 9810 - ] - }, - { - "songId": 159, - "songName": "Gaol", - "musicTabButtonId": 73, - "regionIds": [ - 10031, - 12090, - 10131 - ] - }, - { - "songId": 125, - "songName": "Garden", - "musicTabButtonId": 74, - "regionIds": [ - 12853, - 12953 - ] - }, - { - "songId": 22, - "songName": "Gnome King", - "musicTabButtonId": 75, - "regionIds": [ - 9782, - 9783 - ] - }, - { - "songId": 150, - "songName": "Gnome Theme", - "musicTabButtonId": 76, - "regionIds": [ - 12085 - ] - }, - { - "songId": 33, - "songName": "Gnome Village", - "musicTabButtonId": 77, - "regionIds": [ - 9781 - ] - }, - { - "songId": 101, - "songName": "Gnome Village2", - "musicTabButtonId": 78, - "regionIds": [ - 9269, - 9525 - ] - }, - { - "songId": 23, - "songName": "Gnome", - "musicTabButtonId": 79, - "regionIds": [ - 11830 - ] - }, - { - "songId": 112, - "songName": "Gnomeball", - "musicTabButtonId": 80, - "regionIds": [ - 9270, - 9526, - 9271, - 9527 - ] - }, - { - "songId": 346, - "songName": "Goblin Game", - "musicTabButtonId": 271, - "regionIds": [ - 10393 - ] - }, - { - "songId": 535, - "songName": "Golden Touch", - "musicTabButtonId": 394, - "regionIds": [ - 0 - ] - }, - { - "songId": 116, - "songName": "Greatness", - "musicTabButtonId": 81, - "regionIds": [ - 12596 - ] - }, - { - "songId": 520, - "songName": "Grip of The Talon", - "musicTabButtonId": 377, - "regionIds": [ - 0 - ] - }, - { - "songId": 246, - "songName": "Grotto", - "musicTabButtonId": 212, - "regionIds": [ - 13720 - ] - }, - { - "songId": 466, - "songName": "Ground Scape", - "musicTabButtonId": 347, - "regionIds": [ - 0 - ] - }, - { - "songId": 128, - "songName": "Grumpy", - "musicTabButtonId": 203, - "regionIds": [ - 10286 - ] - }, - { - "songId": 638, - "songName": "Ham Fisted", - "musicTabButtonId": 430, - "regionIds": [ - 0 - ] - }, - { - "songId": 76, - "songName": "Harmony", - "musicTabButtonId": 82, - "regionIds": [ - 12850, - 7507 - ] - }, - { - "songId": 46, - "songName": "Harmony2", - "musicTabButtonId": 192, - "regionIds": [ - 12950 - ] - }, - { - "songId": 277, - "songName": "Haunted Mine", - "musicTabButtonId": 288, - "regionIds": [ - 11077 - ] - }, - { - "songId": 434, - "songName": "Have A Blast", - "musicTabButtonId": 362, - "regionIds": [ - 7757 - ] - }, - { - "songId": 612, - "songName": "Head To Head", - "musicTabButtonId": 421, - "regionIds": [ - 0 - ] - }, - { - "songId": 190, - "songName": "Heart And Mind", - "musicTabButtonId": 200, - "regionIds": [ - 10059 - ] - }, - { - "songId": 4, - "songName": "Hells Bells", - "musicTabButtonId": 293, - "regionIds": [ - 11066, - 11067 - ] - }, - { - "songId": 97, - "songName": "Hermit", - "musicTabButtonId": 220, - "regionIds": [ - 9034 - ] - }, - { - "songId": 55, - "songName": "High Seas", - "musicTabButtonId": 83, - "regionIds": [ - 11057 - ] - }, - { - "songId": 205, - "songName": "High Spirits", - "musicTabButtonId": 459, - "regionIds": [ - 0 - ] - }, - { - "songId": 454, - "songName": "Home Sweet Home", - "musicTabButtonId": 428, - "regionIds": [ - 0 - ] - }, - { - "songId": 621, - "songName": "HomeScape", - "musicTabButtonId": 427, - "regionIds": [ - 0 - ] - }, - { - "songId": 18, - "songName": "Horizon", - "musicTabButtonId": 84, - "regionIds": [ - 11573 - ] - }, - { - "songId": 384, - "songName": "Hypnotized", - "musicTabButtonId": 330, - "regionIds": [ - 0 - ] - }, - { - "songId": 1, - "songName": "Iban", - "musicTabButtonId": 85, - "regionIds": [ - 8519, - 8520, - 8521 - ] - }, - { - "songId": 87, - "songName": "Ice Melody", - "musicTabButtonId": 190, - "regionIds": [ - 11318 - ] - }, - { - "songId": 370, - "songName": "In Between", - "musicTabButtonId": 315, - "regionIds": [ - 10317, - 10061 - ] - }, - { - "songId": 530, - "songName": "In The Brine", - "musicTabButtonId": 401, - "regionIds": [ - 14638 - ] - }, - { - "songId": 511, - "songName": "In The Clink", - "musicTabButtonId": 397, - "regionIds": [ - 8261 - ] - }, - { - "songId": 188, - "songName": "In The Manor", - "musicTabButtonId": 86, - "regionIds": [ - 10287 - ] - }, - { - "songId": 469, - "songName": "In The Pits", - "musicTabButtonId": 366, - "regionIds": [ - 9808 - ] - }, - { - "songId": 519, - "songName": "Incantation", - "musicTabButtonId": 378, - "regionIds": [ - 0 - ] - }, - { - "songId": 260, - "songName": "Insect Queen", - "musicTabButtonId": 228, - "regionIds": [ - 13972, - 14228 - ] - }, - { - "songId": 96, - "songName": "Inspiration", - "musicTabButtonId": 87, - "regionIds": [ - 12087 - ] - }, - { - "songId": 412, - "songName": "Into The Abyss", - "musicTabButtonId": 343, - "regionIds": [ - 12108, - 12107 - ] - }, - { - "songId": 95, - "songName": "Intrepid", - "musicTabButtonId": 88, - "regionIds": [ - 9369, - 9370 - ] - }, - { - "songId": 306, - "songName": "Island Life", - "musicTabButtonId": 280, - "regionIds": [ - 10794, - 11050 - ] - }, - { - "songId": 627, - "songName": "Isle of Everywhere", - "musicTabButtonId": 448, - "regionIds": [ - 0 - ] - }, - { - "songId": 6, - "songName": "Jolly-R", - "musicTabButtonId": 89, - "regionIds": [ - 11058 - ] - }, - { - "songId": 172, - "songName": "Jungle Island", - "musicTabButtonId": 90, - "regionIds": [ - 11309, - 11313 - ] - }, - { - "songId": 479, - "songName": "Jungle Troubles", - "musicTabButtonId": 363, - "regionIds": [ - 11568, - 10055 - ] - }, - { - "songId": 114, - "songName": "Jungly 1", - "musicTabButtonId": 91, - "regionIds": [ - 11054, - 11154 - ] - }, - { - "songId": 115, - "songName": "Jungly 2", - "musicTabButtonId": 92, - "regionIds": [ - 10802 - ] - }, - { - "songId": 117, - "songName": "Jungly 3", - "musicTabButtonId": 93, - "regionIds": [ - 11055 - ] - }, - { - "songId": 362, - "songName": "Karamja Jam", - "musicTabButtonId": 221, - "regionIds": [ - 10900, - 10899 - ] - }, - { - "songId": 9, - "songName": "Kingdom", - "musicTabButtonId": 298, - "regionIds": [ - 11319 - ] - }, - { - "songId": 191, - "songName": "Knightly", - "musicTabButtonId": 94, - "regionIds": [ - 10291 - ] - }, - { - "songId": 134, - "songName": "La Mort", - "musicTabButtonId": 369, - "regionIds": [ - 8779 - ] - }, - { - "songId": 287, - "songName": "Lair", - "musicTabButtonId": 247, - "regionIds": [ - 13975 - ] - }, - { - "songId": 197, - "songName": "Lament of Meiyerditch", - "musicTabButtonId": 452, - "regionIds": [ - 0 - ] - }, - { - "songId": 542, - "songName": "Lament", - "musicTabButtonId": 399, - "regionIds": [ - 12433 - ] - }, - { - "songId": 506, - "songName": "Land Down Under", - "musicTabButtonId": 424, - "regionIds": [ - 0 - ] - }, - { - "songId": 396, - "songName": "Land of the Dwarves", - "musicTabButtonId": 342, - "regionIds": [ - 11423 - ] - }, - { - "songId": 164, - "songName": "Landlubber", - "musicTabButtonId": 194, - "regionIds": [ - 10801 - ] - }, - { - "songId": 546, - "songName": "Last Stand", - "musicTabButtonId": 419, - "regionIds": [ - 0 - ] - }, - { - "songId": 60, - "songName": "Lasting", - "musicTabButtonId": 95, - "regionIds": [ - 10549 - ] - }, - { - "songId": 293, - "songName": "Legend", - "musicTabButtonId": 241, - "regionIds": [ - 10808, - 11064 - ] - }, - { - "songId": 66, - "songName": "Legion", - "musicTabButtonId": 96, - "regionIds": [ - 10039, - 10295, - 12089 - ] - }, - { - "songId": 631, - "songName": "Life's A Beach!", - "musicTabButtonId": 433, - "regionIds": [ - 0 - ] - }, - { - "songId": 320, - "songName": "Lighthouse", - "musicTabButtonId": 267, - "regionIds": [ - 10040, - 9799 - ] - }, - { - "songId": 113, - "songName": "Lightness", - "musicTabButtonId": 97, - "regionIds": [ - 12599 - ] - }, - { - "songId": 74, - "songName": "Lightwalk", - "musicTabButtonId": 98, - "regionIds": [ - 11061 - ] - }, - { - "songId": 632, - "songName": "Little Cave of Horrors", - "musicTabButtonId": 434, - "regionIds": [ - 0 - ] - }, - { - "songId": 168, - "songName": "Lonesome", - "musicTabButtonId": 187, - "regionIds": [ - 13203 - ] - }, - { - "songId": 161, - "songName": "Long Ago", - "musicTabButtonId": 99, - "regionIds": [ - 10544 - ] - }, - { - "songId": 12, - "songName": "Long Way Home", - "musicTabButtonId": 100, - "regionIds": [ - 11826 - ] - }, - { - "songId": 253, - "songName": "Lost Soul", - "musicTabButtonId": 233, - "regionIds": [ - 9008, - 9264 - ] - }, - { - "songId": 20, - "songName": "Lullaby", - "musicTabButtonId": 102, - "regionIds": [ - 13365, - 10551 - ] - }, - { - "songId": 264, - "songName": "Mad Eadgar", - "musicTabButtonId": 225, - "regionIds": [ - 11677 - ] - }, - { - "songId": 13, - "songName": "Mage Arena", - "musicTabButtonId": 103, - "regionIds": [ - 12348, - 12349, - 10057 - ] - }, - { - "songId": 185, - "songName": "Magic Dance", - "musicTabButtonId": 104, - "regionIds": [ - 10288 - ] - }, - { - "songId": 184, - "songName": "Magical Journey", - "musicTabButtonId": 105, - "regionIds": [ - 10805 - ] - }, - { - "songId": 544, - "songName": "Making Waves", - "musicTabButtonId": 420, - "regionIds": [ - 9272, - 9528, - 9273 - ] - }, - { - "songId": 559, - "songName": "Malady", - "musicTabButtonId": 439, - "regionIds": [ - 0 - ] - }, - { - "songId": 328, - "songName": "March", - "musicTabButtonId": 101, - "regionIds": [ - 10036 - ] - }, - { - "songId": 304, - "songName": "Marooned", - "musicTabButtonId": 279, - "regionIds": [ - 11562, - 12117 - ] - }, - { - "songId": 261, - "songName": "Marzipan", - "musicTabButtonId": 226, - "regionIds": [ - 11421, - 11167, - 11166 - ] - }, - { - "songId": 340, - "songName": "Masquerade", - "musicTabButtonId": 300, - "regionIds": [ - 10908 - ] - }, - { - "songId": 577, - "songName": "Mastermindless", - "musicTabButtonId": 407, - "regionIds": [ - 0 - ] - }, - { - "songId": 156, - "songName": "Mausoleum", - "musicTabButtonId": 209, - "regionIds": [ - 13722 - ] - }, - { - "songId": 508, - "songName": "Meddling Kids", - "musicTabButtonId": 425, - "regionIds": [ - 0 - ] - }, - { - "songId": 157, - "songName": "Medieval", - "musicTabButtonId": 106, - "regionIds": [ - 13109 - ] - }, - { - "songId": 193, - "songName": "Mellow", - "musicTabButtonId": 107, - "regionIds": [ - 10293 - ] - }, - { - "songId": 317, - "songName": "Melodrama", - "musicTabButtonId": 286, - "regionIds": [ - 9776 - ] - }, - { - "songId": 254, - "songName": "Meridian", - "musicTabButtonId": 234, - "regionIds": [ - 8497, - 8753, - 9287 - ] - }, - { - "songId": 600, - "songName": "Method of Madness", - "musicTabButtonId": 412, - "regionIds": [ - 0 - ] - }, - { - "songId": 107, - "songName": "Miles Away", - "musicTabButtonId": 108, - "regionIds": [ - 11571, - 10569 - ] - }, - { - "songId": 534, - "songName": "Mind Over Matter", - "musicTabButtonId": 395, - "regionIds": [ - 0 - ] - }, - { - "songId": 65, - "songName": "Miracle Dance", - "musicTabButtonId": 109, - "regionIds": [ - 11083 - ] - }, - { - "songId": 388, - "songName": "Mirage", - "musicTabButtonId": 331, - "regionIds": [ - 13199 - ] - }, - { - "songId": 284, - "songName": "Miscellania", - "musicTabButtonId": 274, - "regionIds": [ - 10044 - ] - }, - { - "songId": 200, - "songName": "The Mollusc Menace", - "musicTabButtonId": 455, - "regionIds": [ - 0 - ] - }, - { - "songId": 21, - "songName": "Monarch Waltz", - "musicTabButtonId": 110, - "regionIds": [ - 10807 - ] - }, - { - "songId": 303, - "songName": "Monkey Madness", - "musicTabButtonId": 278, - "regionIds": [ - 11051 - ] - }, - { - "songId": 343, - "songName": "Monster Melee", - "musicTabButtonId": 310, - "regionIds": [ - 12694 - ] - }, - { - "songId": 10, - "songName": "Moody", - "musicTabButtonId": 111, - "regionIds": [ - 9523, - 9779, - 12600 - ] - }, - { - "songId": 48, - "songName": "Morytania", - "musicTabButtonId": 210, - "regionIds": [ - 13622 - ] - }, - { - "songId": 515, - "songName": "Mudskipper Melody", - "musicTabButtonId": 371, - "regionIds": [ - 11824 - ] - }, - { - "songId": 203, - "songName": "My Arm's Journey", - "musicTabButtonId": 457, - "regionIds": [ - 0 - ] - }, - { - "songId": 348, - "songName": "Narnode's Theme", - "musicTabButtonId": 275, - "regionIds": [ - 9882 - ] - }, - { - "songId": 245, - "songName": "Natural", - "musicTabButtonId": 213, - "regionIds": [ - 13620, - 9038 - ] - }, - { - "songId": 155, - "songName": "Neverland", - "musicTabButtonId": 112, - "regionIds": [ - 9780 - ] - }, - { - "songId": 62, - "songName": "Newbie Melody", - "musicTabButtonId": 113, - "regionIds": [ - 12080, - 12336, - 12592, - 12079, - 12335 - ] - }, - { - "songId": 646, - "songName": "Night of The Vampyre", - "musicTabButtonId": 454, - "regionIds": [ - 0 - ] - }, - { - "songId": 127, - "songName": "Nightfall", - "musicTabButtonId": 114, - "regionIds": [ - 11827, - 12861 - ] - }, - { - "songId": 594, - "songName": "No Way Out", - "musicTabButtonId": 413, - "regionIds": [ - 0 - ] - }, - { - "songId": 58, - "songName": "Nomad", - "musicTabButtonId": 201, - "regionIds": [ - 11056 - ] - }, - { - "songId": 587, - "songName": "Null And Void", - "musicTabButtonId": 416, - "regionIds": [ - 10537 - ] - }, - { - "songId": 633, - "songName": "On The Wing", - "musicTabButtonId": 440, - "regionIds": [ - 0 - ] - }, - { - "songId": 103, - "songName": "Oriental", - "musicTabButtonId": 115, - "regionIds": [ - 11666, - 11668 - ] - }, - { - "songId": 322, - "songName": "Out of The Deep", - "musicTabButtonId": 268, - "regionIds": [ - 10140, - 10056 - ] - }, - { - "songId": 447, - "songName": "Over To Nardah", - "musicTabButtonId": 387, - "regionIds": [ - 13613 - ] - }, - { - "songId": 256, - "songName": "Overpass", - "musicTabButtonId": 237, - "regionIds": [ - 9267 - ] - }, - { - "songId": 7, - "songName": "Overture", - "musicTabButtonId": 116, - "regionIds": [ - 10806 - ] - }, - { - "songId": 93, - "songName": "Parade", - "musicTabButtonId": 117, - "regionIds": [ - 13110, - 13366 - ] - }, - { - "songId": 393, - "songName": "Path of Peril", - "musicTabButtonId": 323, - "regionIds": [ - 10575, - 10831 - ] - }, - { - "songId": 364, - "songName": "Pathways", - "musicTabButtonId": 297, - "regionIds": [ - 10901 - ] - }, - { - "songId": 588, - "songName": "Pest Control", - "musicTabButtonId": 417, - "regionIds": [ - 10536 - ] - }, - { - "songId": 505, - "songName": "Pharaoh's Tomb", - "musicTabButtonId": 398, - "regionIds": [ - 13356, - 12105 - ] - }, - { - "songId": 354, - "songName": "Phasmatys", - "musicTabButtonId": 307, - "regionIds": [ - 14746 - ] - }, - { - "songId": 419, - "songName": "Pheasant Peasant", - "musicTabButtonId": 354, - "regionIds": [ - 10314 - ] - }, - { - "songId": 614, - "songName": "Pinball Wizard", - "musicTabButtonId": 422, - "regionIds": [ - 0 - ] - }, - { - "songId": 149, - "songName": "Principality", - "musicTabButtonId": 219, - "regionIds": [ - 11575 - ] - }, - { - "songId": 334, - "songName": "Pirates of Peril", - "musicTabButtonId": 263, - "regionIds": [ - 12093 - ] - }, - { - "songId": 158, - "songName": "Quest", - "musicTabButtonId": 118, - "regionIds": [ - 10315 - ] - }, - { - "songId": 482, - "songName": "Rat A Tat Tat", - "musicTabButtonId": 382, - "regionIds": [ - 11599 - ] - }, - { - "songId": 491, - "songName": "Rat Hunt", - "musicTabButtonId": 383, - "regionIds": [ - 11343 - ] - }, - { - "songId": 318, - "songName": "Ready For Battle", - "musicTabButtonId": 287, - "regionIds": [ - 0 - ] - }, - { - "songId": 329, - "songName": "Regal", - "musicTabButtonId": 119, - "regionIds": [ - 13117 - ] - }, - { - "songId": 78, - "songName": "Reggae", - "musicTabButtonId": 120, - "regionIds": [ - 11565, - 11821 - ] - }, - { - "songId": 89, - "songName": "Reggae2", - "musicTabButtonId": 121, - "regionIds": [ - 11567 - ] - }, - { - "songId": 289, - "songName": "Rellekka", - "musicTabButtonId": 259, - "regionIds": [ - 10297, - 10553, - 10554 - ] - }, - { - "songId": 44, - "songName": "Right On Track", - "musicTabButtonId": 351, - "regionIds": [ - 7501 - ] - }, - { - "songId": 262, - "songName": "Righteousness", - "musicTabButtonId": 227, - "regionIds": [ - 9803 - ] - }, - { - "songId": 91, - "songName": "Riverside", - "musicTabButtonId": 122, - "regionIds": [ - 8496, - 10803 - ] - }, - { - "songId": 204, - "songName": "Roc and Roll", - "musicTabButtonId": 458, - "regionIds": [ - 0 - ] - }, - { - "songId": 533, - "songName": "Roll The Bones", - "musicTabButtonId": 396, - "regionIds": [ - 0 - ] - }, - { - "songId": 335, - "songName": "Romancing The Crone", - "musicTabButtonId": 294, - "regionIds": [ - 11068 - ] - }, - { - "songId": 390, - "songName": "Romper Chomper", - "musicTabButtonId": 338, - "regionIds": [ - 9263, - 9519 - ] - }, - { - "songId": 53, - "songName": "Royale", - "musicTabButtonId": 123, - "regionIds": [ - 11671 - ] - }, - { - "songId": 57, - "songName": "Rune Essence", - "musicTabButtonId": 124, - "regionIds": [ - 11595 - ] - }, - { - "songId": 5, - "songName": "Sad Meadow", - "musicTabButtonId": 125, - "regionIds": [ - 10035 - ] - }, - { - "songId": 290, - "songName": "Saga", - "musicTabButtonId": 240, - "regionIds": [ - 10296, - 10552 - ] - }, - { - "songId": 359, - "songName": "Sarcophagus", - "musicTabButtonId": 324, - "regionIds": [ - 12945 - ] - }, - { - "songId": 490, - "songName": "Sarim's Vermin", - "musicTabButtonId": 384, - "regionIds": [ - 11926 - ] - }, - { - "songId": 144, - "songName": "Scape Cave", - "musicTabButtonId": 126, - "regionIds": [ - 12436, - 12698, - 13210, - 12954 - ] - }, - { - "songId": 0, - "songName": "Scape Main", - "musicTabButtonId": 318, - "regionIds": [ - 0 - ] - }, - { - "songId": 400, - "songName": "Scape Original", - "musicTabButtonId": 127, - "regionIds": [ - 0 - ] - }, - { - "songId": 331, - "songName": "Scape Sad", - "musicTabButtonId": 128, - "regionIds": [ - 13116, - 13372 - ] - }, - { - "songId": 547, - "songName": "Scape Santa", - "musicTabButtonId": 292, - "regionIds": [ - 0 - ] - }, - { - "songId": 321, - "songName": "Scape Scared", - "musicTabButtonId": 262, - "regionIds": [ - 0 - ] - }, - { - "songId": 54, - "songName": "Scape Soft", - "musicTabButtonId": 184, - "regionIds": [ - 11829 - ] - }, - { - "songId": 332, - "songName": "Scape Wild", - "musicTabButtonId": 129, - "regionIds": [ - 12857, - 12604, - 12860 - ] - }, - { - "songId": 352, - "songName": "Scarab", - "musicTabButtonId": 328, - "regionIds": [ - 12589, - 12845, - 13101, - 11085, - 11341, - 11597 - ] - }, - { - "songId": 35, - "songName": "Sea Shanty 2", - "musicTabButtonId": 131, - "regionIds": [ - 12082 - ] - }, - { - "songId": 92, - "songName": "Sea Shanty", - "musicTabButtonId": 130, - "regionIds": [ - 11569 - ] - }, - { - "songId": 110, - "songName": "Serenade", - "musicTabButtonId": 132, - "regionIds": [ - 9521, - 9777 - ] - }, - { - "songId": 52, - "songName": "Serene", - "musicTabButtonId": 133, - "regionIds": [ - 11936, - 11937, - 11339, - 11837 - ] - }, - { - "songId": 356, - "songName": "Settlement", - "musicTabButtonId": 312, - "regionIds": [ - 11065 - ] - }, - { - "songId": 286, - "songName": "Shadowland", - "musicTabButtonId": 249, - "regionIds": [ - 13618, - 13875, - 8526 - ] - }, - { - "songId": 122, - "songName": "Shine", - "musicTabButtonId": 134, - "regionIds": [ - 13363 - ] - }, - { - "songId": 120, - "songName": "Shining", - "musicTabButtonId": 186, - "regionIds": [ - 12858 - ] - }, - { - "songId": 353, - "songName": "Shipwrecked", - "musicTabButtonId": 306, - "regionIds": [ - 14391 - ] - }, - { - "songId": 311, - "songName": "Showdown", - "musicTabButtonId": 283, - "regionIds": [ - 10895 - ] - }, - { - "songId": 640, - "songName": "Sigmund's Showdown", - "musicTabButtonId": 431, - "regionIds": [ - 0 - ] - }, - { - "songId": 257, - "songName": "Sojourn", - "musicTabButtonId": 224, - "regionIds": [ - 11321, - 11577 - ] - }, - { - "songId": 80, - "songName": "Soundscape", - "musicTabButtonId": 135, - "regionIds": [ - 9774, - 10030 - ] - }, - { - "songId": 387, - "songName": "Sphinx", - "musicTabButtonId": 329, - "regionIds": [ - 13100 - ] - }, - { - "songId": 175, - "songName": "Spirit", - "musicTabButtonId": 136, - "regionIds": [ - 12597 - ] - }, - { - "songId": 462, - "songName": "Spirits of The Elid", - "musicTabButtonId": 388, - "regionIds": [ - 13461 - ] - }, - { - "songId": 77, - "songName": "Splendour", - "musicTabButtonId": 137, - "regionIds": [ - 11574 - ] - }, - { - "songId": 129, - "songName": "Spooky Jungle", - "musicTabButtonId": 139, - "regionIds": [ - 11053 - ] - }, - { - "songId": 333, - "songName": "Spooky", - "musicTabButtonId": 138, - "regionIds": [ - 12340 - ] - }, - { - "songId": 11, - "songName": "Spooky2", - "musicTabButtonId": 289, - "regionIds": [ - 13718, - 13974 - ] - }, - { - "songId": 241, - "songName": "Stagnant", - "musicTabButtonId": 215, - "regionIds": [ - 13876, - 8782 - ] - }, - { - "songId": 108, - "songName": "Starlight", - "musicTabButtonId": 140, - "regionIds": [ - 12181, - 11925 - ] - }, - { - "songId": 151, - "songName": "Start", - "musicTabButtonId": 172, - "regionIds": [ - 12339 - ] - }, - { - "songId": 111, - "songName": "Still Night", - "musicTabButtonId": 141, - "regionIds": [ - 13108 - ] - }, - { - "songId": 319, - "songName": "Stillness", - "musicTabButtonId": 296, - "regionIds": [ - 13977 - ] - }, - { - "songId": 292, - "songName": "Stranded", - "musicTabButtonId": 295, - "regionIds": [ - 11322, - 11578 - ] - }, - { - "songId": 470, - "songName": "Strange Place", - "musicTabButtonId": 364, - "regionIds": [ - 7494 - ] - }, - { - "songId": 243, - "songName": "Stratosphere", - "musicTabButtonId": 207, - "regionIds": [ - 8523 - ] - }, - { - "songId": 568, - "songName": "Storm Brew", - "musicTabButtonId": 402, - "regionIds": [ - 10577 - ] - }, - { - "songId": 517, - "songName": "Subterranea", - "musicTabButtonId": 375, - "regionIds": [ - 10142, - 10398 - ] - }, - { - "songId": 267, - "songName": "Sunburn", - "musicTabButtonId": 242, - "regionIds": [ - 12846, - 13357 - ] - }, - { - "songId": 265, - "songName": "Superstition", - "musicTabButtonId": 257, - "regionIds": [ - 11153 - ] - }, - { - "songId": 308, - "songName": "Suspicious", - "musicTabButtonId": 282, - "regionIds": [ - 10567, - 10311 - ] - }, - { - "songId": 395, - "songName": "Tale of Keldagrim", - "musicTabButtonId": 341, - "regionIds": [ - 11678, - 11679 - ] - }, - { - "songId": 140, - "songName": "Talking Forest", - "musicTabButtonId": 173, - "regionIds": [ - 10550 - ] - }, - { - "songId": 397, - "songName": "Tears of Guthix", - "musicTabButtonId": 332, - "regionIds": [ - 12948 - ] - }, - { - "songId": 296, - "songName": "Technology", - "musicTabButtonId": 277, - "regionIds": [ - 10566, - 10310, - 9626 - ] - }, - { - "songId": 376, - "songName": "Temple of Light", - "musicTabButtonId": 368, - "regionIds": [ - 7496 - ] - }, - { - "songId": 307, - "songName": "Temple", - "musicTabButtonId": 281, - "regionIds": [ - 11151 - ] - }, - { - "songId": 478, - "songName": "The Cellar Dwellers", - "musicTabButtonId": 361, - "regionIds": [ - 10135, - 10391 - ] - }, - { - "songId": 425, - "songName": "The Chosen", - "musicTabButtonId": 346, - "regionIds": [ - 9805 - ] - }, - { - "songId": 79, - "songName": "The Desert", - "musicTabButtonId": 142, - "regionIds": [ - 12591, - 12847 - ] - }, - { - "songId": 461, - "songName": "The Desolate Isle", - "musicTabButtonId": 352, - "regionIds": [ - 10042 - ] - }, - { - "songId": 541, - "songName": "The Enchanter", - "musicTabButtonId": 393, - "regionIds": [ - 13462 - ] - }, - { - "songId": 403, - "songName": "The Far Side", - "musicTabButtonId": 345, - "regionIds": [ - 12111 - ] - }, - { - "songId": 630, - "songName": "The Galleon", - "musicTabButtonId": 450, - "regionIds": [ - 0 - ] - }, - { - "songId": 464, - "songName": "The Genie", - "musicTabButtonId": 386, - "regionIds": [ - 13457 - ] - }, - { - "songId": 377, - "songName": "The Golem", - "musicTabButtonId": 319, - "regionIds": [ - 13616, - 13872 - ] - }, - { - "songId": 643, - "songName": "The Last Shanty", - "musicTabButtonId": 453, - "regionIds": [ - 0 - ] - }, - { - "songId": 407, - "songName": "The Lost Melody", - "musicTabButtonId": 339, - "regionIds": [ - 13206 - ] - }, - { - "songId": 420, - "songName": "The Lost Tribe", - "musicTabButtonId": 340, - "regionIds": [ - 0 - ] - }, - { - "songId": 625, - "songName": "The Lunar Isle", - "musicTabButtonId": 447, - "regionIds": [ - 0 - ] - }, - { - "songId": 573, - "songName": "The Mad Mole", - "musicTabButtonId": 403, - "regionIds": [ - 6992, - 6993 - ] - }, - { - "songId": 448, - "songName": "The Monsters Below", - "musicTabButtonId": 353, - "regionIds": [ - 9886 - ] - }, - { - "songId": 316, - "songName": "The Navigator", - "musicTabButtonId": 261, - "regionIds": [ - 0 - ] - }, - { - "songId": 485, - "songName": "The Noble Rodent", - "musicTabButtonId": 381, - "regionIds": [ - 0 - ] - }, - { - "songId": 355, - "songName": "The Other Side", - "musicTabButtonId": 308, - "regionIds": [ - 14646, - 14647 - ] - }, - { - "songId": 398, - "songName": "The Power of Tears", - "musicTabButtonId": 333, - "regionIds": [ - 0 - ] - }, - { - "songId": 202, - "songName": "Prime Time", - "musicTabButtonId": 456, - "regionIds": [ - 0 - ] - }, - { - "songId": 413, - "songName": "The Quizmaster", - "musicTabButtonId": 356, - "regionIds": [ - 7754 - ] - }, - { - "songId": 402, - "songName": "The Rogues Den", - "musicTabButtonId": 344, - "regionIds": [ - 11855, - 11854, - 12110, - 12109 - ] - }, - { - "songId": 170, - "songName": "The Shadow", - "musicTabButtonId": 143, - "regionIds": [ - 11314, - 11315 - ] - }, - { - "songId": 341, - "songName": "The Slayer", - "musicTabButtonId": 302, - "regionIds": [ - 11164 - ] - }, - { - "songId": 510, - "songName": "Slither and Thither", - "musicTabButtonId": 426, - "regionIds": [ - 0 - ] - }, - { - "songId": 201, - "songName": "Slug a bug Ball", - "musicTabButtonId": 266, - "regionIds": [ - 0 - ] - }, - { - "songId": 339, - "songName": "The Terrible Tower", - "musicTabButtonId": 301, - "regionIds": [ - 13623 - ] - }, - { - "songId": 133, - "songName": "The Tower", - "musicTabButtonId": 144, - "regionIds": [ - 10292, - 10136, - 10392 - ] - }, - { - "songId": 109, - "songName": "Theme", - "musicTabButtonId": 174, - "regionIds": [ - 10294, - 10138, - 10394 - ] - }, - { - "songId": 379, - "songName": "Throne of The Demon", - "musicTabButtonId": 321, - "regionIds": [ - 0 - ] - }, - { - "songId": 242, - "songName": "Time Out", - "musicTabButtonId": 218, - "regionIds": [ - 11591 - ] - }, - { - "songId": 369, - "songName": "Time To Mine", - "musicTabButtonId": 314, - "regionIds": [ - 11422 - ] - }, - { - "songId": 338, - "songName": "Tiptoe", - "musicTabButtonId": 269, - "regionIds": [ - 12440 - ] - }, - { - "songId": 525, - "songName": "Title Fight", - "musicTabButtonId": 389, - "regionIds": [ - 12696 - ] - }, - { - "songId": 591, - "songName": "Tomb Raider", - "musicTabButtonId": 444, - "regionIds": [ - 0 - ] - }, - { - "songId": 105, - "songName": "Tomorrow", - "musicTabButtonId": 188, - "regionIds": [ - 12081 - ] - }, - { - "songId": 582, - "songName": "Too Many Cooks...", - "musicTabButtonId": 408, - "regionIds": [ - 11930 - ] - }, - { - "songId": 51, - "songName": "Trawler Minor", - "musicTabButtonId": 146, - "regionIds": [ - 7755, - 8011 - ] - }, - { - "songId": 38, - "songName": "Trawler", - "musicTabButtonId": 145, - "regionIds": [ - 7499, - 8012 - ] - }, - { - "songId": 130, - "songName": "Tree Spirits", - "musicTabButtonId": 147, - "regionIds": [ - 9268, - 9524 - ] - }, - { - "songId": 187, - "songName": "Tremble", - "musicTabButtonId": 223, - "regionIds": [ - 11320 - ] - }, - { - "songId": 94, - "songName": "Tribal 2", - "musicTabButtonId": 150, - "regionIds": [ - 11566, - 11822 - ] - }, - { - "songId": 162, - "songName": "Tribal Background", - "musicTabButtonId": 148, - "regionIds": [ - 11312, - 11412 - ] - }, - { - "songId": 165, - "songName": "Tribal", - "musicTabButtonId": 149, - "regionIds": [ - 11311 - ] - }, - { - "songId": 192, - "songName": "Trinity", - "musicTabButtonId": 151, - "regionIds": [ - 10804, - 10904 - ] - }, - { - "songId": 611, - "songName": "Trouble Brewing", - "musicTabButtonId": 435, - "regionIds": [ - 0 - ] - }, - { - "songId": 183, - "songName": "Troubled", - "musicTabButtonId": 152, - "regionIds": [ - 11833 - ] - }, - { - "songId": 88, - "songName": "Twilight", - "musicTabButtonId": 208, - "regionIds": [ - 10906 - ] - }, - { - "songId": 473, - "songName": "Tzhaar!", - "musicTabButtonId": 367, - "regionIds": [ - 9551 - ] - }, - { - "songId": 176, - "songName": "Undercurrent", - "musicTabButtonId": 195, - "regionIds": [ - 12345 - ] - }, - { - "songId": 179, - "songName": "Underground", - "musicTabButtonId": 153, - "regionIds": [ - 13368, - 11416 - ] - }, - { - "songId": 323, - "songName": "Underground Pass", - "musicTabButtonId": 157, - "regionIds": [ - 9622, - 9621 - ] - }, - { - "songId": 131, - "songName": "Understanding", - "musicTabButtonId": 206, - "regionIds": [ - 9547 - ] - }, - { - "songId": 3, - "songName": "Unknown Land", - "musicTabButtonId": 156, - "regionIds": [ - 12338, - 8524 - ] - }, - { - "songId": 70, - "songName": "Upcoming", - "musicTabButtonId": 158, - "regionIds": [ - 10546 - ] - }, - { - "songId": 75, - "songName": "Venture", - "musicTabButtonId": 159, - "regionIds": [ - 13364 - ] - }, - { - "songId": 45, - "songName": "Venture2", - "musicTabButtonId": 193, - "regionIds": [ - 13465, - 13464 - ] - }, - { - "songId": 528, - "songName": "Victory Is Mine", - "musicTabButtonId": 390, - "regionIds": [ - 0 - ] - }, - { - "songId": 61, - "songName": "Village", - "musicTabButtonId": 211, - "regionIds": [ - 13878 - ] - }, - { - "songId": 85, - "songName": "Vision", - "musicTabButtonId": 160, - "regionIds": [ - 12337, - 12437 - ] - }, - { - "songId": 30, - "songName": "Voodoo Cult", - "musicTabButtonId": 161, - "regionIds": [ - 11665, - 9545 - ] - }, - { - "songId": 32, - "songName": "Voyage", - "musicTabButtonId": 162, - "regionIds": [ - 10038 - ] - }, - { - "songId": 622, - "songName": "Waking Dream", - "musicTabButtonId": 445, - "regionIds": [ - 0 - ] - }, - { - "songId": 49, - "songName": "Wander", - "musicTabButtonId": 163, - "regionIds": [ - 12083 - ] - }, - { - "songId": 295, - "songName": "Warrior", - "musicTabButtonId": 260, - "regionIds": [ - 10653 - ] - }, - { - "songId": 634, - "songName": "Warriors' Guild", - "musicTabButtonId": 429, - "regionIds": [ - 0 - ] - }, - { - "songId": 82, - "songName": "Waterfall", - "musicTabButtonId": 164, - "regionIds": [ - 10037, - 10137 - ] - }, - { - "songId": 244, - "songName": "Waterlogged", - "musicTabButtonId": 214, - "regionIds": [ - 13877, - 14133, - 8014, - 8270 - ] - }, - { - "songId": 626, - "songName": "Way of The Enchanter", - "musicTabButtonId": 449, - "regionIds": [ - 0 - ] - }, - { - "songId": 394, - "songName": "Wayward", - "musicTabButtonId": 336, - "regionIds": [ - 9875 - ] - }, - { - "songId": 126, - "songName": "We Are The Fairies", - "musicTabButtonId": 441, - "regionIds": [ - 0 - ] - }, - { - "songId": 271, - "songName": "Well of Voyage", - "musicTabButtonId": 230, - "regionIds": [ - 9366 - ] - }, - { - "songId": 475, - "songName": "Wild Side", - "musicTabButtonId": 360, - "regionIds": [ - 12092, - 12348 - ] - }, - { - "songId": 435, - "songName": "Wilderness", - "musicTabButtonId": 165, - "regionIds": [ - 11832, - 12346 - ] - }, - { - "songId": 42, - "songName": "Wilderness2", - "musicTabButtonId": 166, - "regionIds": [ - 12091, - 12347 - ] - }, - { - "songId": 43, - "songName": "Wilderness3", - "musicTabButtonId": 167, - "regionIds": [ - 11834 - ] - }, - { - "songId": 8, - "songName": "Wildwood", - "musicTabButtonId": 250, - "regionIds": [ - 12344 - ] - }, - { - "songId": 14, - "songName": "Witching", - "musicTabButtonId": 168, - "regionIds": [ - 13114, - 13370 - ] - }, - { - "songId": 529, - "songName": "Woe of The Wyvern", - "musicTabButtonId": 391, - "regionIds": [ - 0 - ] - }, - { - "songId": 189, - "songName": "Wolf Mountain", - "musicTabButtonId": 191, - "regionIds": [ - 12603, - 12859 - ] - }, - { - "songId": 34, - "songName": "Wonder", - "musicTabButtonId": 169, - "regionIds": [ - 11831 - ] - }, - { - "songId": 81, - "songName": "Wonderous", - "musicTabButtonId": 170, - "regionIds": [ - 10548 - ] - }, - { - "songId": 255, - "songName": "Woodland", - "musicTabButtonId": 235, - "regionIds": [ - 8498, - 8754 - ] - }, - { - "songId": 15, - "songName": "Workshop", - "musicTabButtonId": 171, - "regionIds": [ - 12084 - ] - }, - { - "songId": 565, - "songName": "Wrath And Ruin", - "musicTabButtonId": 414, - "regionIds": [ - 0 - ] - }, - { - "songId": 524, - "songName": "Xenophobe", - "musicTabButtonId": 376, - "regionIds": [ - 7492, - 11589 - ] - }, - { - "songId": 145, - "songName": "Yesteryear", - "musicTabButtonId": 185, - "regionIds": [ - 12849 - ] - }, - { - "songId": 146, - "songName": "Zealot", - "musicTabButtonId": 196, - "regionIds": [ - 10827 - ] - }, - { - "songId": 392, - "songName": "Zogre Dance", - "musicTabButtonId": 337, - "regionIds": [ - 9775 - ] - } - ] + "musicRegions": [ + { + "songId": 363, + "songName": "7th Realm", + "musicTabButtonId": 299, + "regionIds": [10645, 10644] + }, + { + "songId": 177, + "songName": "Adventure", + "musicTabButtonId": 25, + "regionIds": [12854] + }, + { + "songId": 50, + "songName": "Al-Kharid", + "musicTabButtonId": 26, + "regionIds": [13105, 13361] + }, + { + "songId": 73, + "songName": "All's Fairy In Love'N'War", + "musicTabButtonId": 443, + "regionIds": [0] + }, + { + "songId": 102, + "songName": "Alone", + "musicTabButtonId": 27, + "regionIds": [12086, 10390, 10134] + }, + { + "songId": 90, + "songName": "Ambient Jungle", + "musicTabButtonId": 28, + "regionIds": [11310] + }, + { + "songId": 305, + "songName": "Anywhere", + "musicTabButtonId": 276, + "regionIds": [10795] + }, + { + "songId": 123, + "songName": "Arabian 2", + "musicTabButtonId": 30, + "regionIds": [13107] + }, + { + "songId": 124, + "songName": "Arabian 3", + "musicTabButtonId": 31, + "regionIds": [12848] + }, + { + "songId": 36, + "songName": "Arabian", + "musicTabButtonId": 29, + "regionIds": [13617, 13106] + }, + { + "songId": 19, + "songName": "Arabique", + "musicTabButtonId": 32, + "regionIds": [11417] + }, + { + "songId": 160, + "songName": "Army of Darkness", + "musicTabButtonId": 33, + "regionIds": [12088] + }, + { + "songId": 186, + "songName": "Arrival", + "musicTabButtonId": 34, + "regionIds": [11572] + }, + { + "songId": 247, + "songName": "Artistry", + "musicTabButtonId": 245, + "regionIds": [8010] + }, + { + "songId": 24, + "songName": "Attack 1", + "musicTabButtonId": 35, + "regionIds": [10034] + }, + { + "songId": 25, + "songName": "Attack 2", + "musicTabButtonId": 36, + "regionIds": [11414] + }, + { + "songId": 26, + "songName": "Attack 3", + "musicTabButtonId": 37, + "regionIds": [0] + }, + { + "songId": 27, + "songName": "Attack 4", + "musicTabButtonId": 38, + "regionIds": [10289] + }, + { + "songId": 28, + "songName": "Attack 5", + "musicTabButtonId": 39, + "regionIds": [9033] + }, + { + "songId": 29, + "songName": "Attack 6", + "musicTabButtonId": 40, + "regionIds": [10387] + }, + { + "songId": 180, + "songName": "Attention", + "musicTabButtonId": 41, + "regionIds": [11825] + }, + { + "songId": 2, + "songName": "Autumn Voyage", + "musicTabButtonId": 42, + "regionIds": [12851] + }, + { + "songId": 497, + "songName": "Aye Car Rum Ba", + "musicTabButtonId": 373, + "regionIds": [8527] + }, + { + "songId": 248, + "songName": "Aztec", + "musicTabButtonId": 217, + "regionIds": [11157, 11158, 11156, 10902] + }, + { + "songId": 324, + "songName": "Background", + "musicTabButtonId": 43, + "regionIds": [11060, 11316, 7758] + }, + { + "songId": 152, + "songName": "Ballad of Enchantment", + "musicTabButtonId": 44, + "regionIds": [10290] + }, + { + "songId": 263, + "songName": "Bandit Camp", + "musicTabButtonId": 243, + "regionIds": [12590] + }, + { + "songId": 141, + "songName": "Barbarianism", + "musicTabButtonId": 253, + "regionIds": [12341, 12441] + }, + { + "songId": 345, + "songName": "Barking Mad", + "musicTabButtonId": 305, + "regionIds": [14234] + }, + { + "songId": 99, + "songName": "Baroque", + "musicTabButtonId": 45, + "regionIds": [10547] + }, + { + "songId": 100, + "songName": "Beyond", + "musicTabButtonId": 46, + "regionIds": [11675, 11419, 11418] + }, + { + "songId": 83, + "songName": "Big Chords", + "musicTabButtonId": 47, + "regionIds": [10032, 11593] + }, + { + "songId": 498, + "songName": "Blistering Barnacles", + "musicTabButtonId": 372, + "regionIds": [8528] + }, + { + "songId": 342, + "songName": "Body Parts", + "musicTabButtonId": 304, + "regionIds": [13979, 14235] + }, + { + "songId": 154, + "songName": "Bone Dance", + "musicTabButtonId": 248, + "regionIds": [13619] + }, + { + "songId": 266, + "songName": "Bone Dry", + "musicTabButtonId": 322, + "regionIds": [12946, 13202] + }, + { + "songId": 64, + "songName": "Book of Spells", + "musicTabButtonId": 48, + "regionIds": [12593] + }, + { + "songId": 291, + "songName": "Borderland", + "musicTabButtonId": 258, + "regionIds": [10809, 10810] + }, + { + "songId": 132, + "songName": "Breeze", + "musicTabButtonId": 229, + "regionIds": [9010] + }, + { + "songId": 471, + "songName": "Brew Hoo Hoo", + "musicTabButtonId": 357, + "regionIds": [14747] + }, + { + "songId": 194, + "songName": "Brimstail's Scales", + "musicTabButtonId": 451, + "regionIds": [9625] + }, + { + "songId": 489, + "songName": "Bubble And Squeak", + "musicTabButtonId": 380, + "regionIds": [7753] + }, + { + "songId": 545, + "songName": "Cabin Fever", + "musicTabButtonId": 400, + "regionIds": [0] + }, + { + "songId": 104, + "songName": "Camelot", + "musicTabButtonId": 49, + "regionIds": [11062, 11063] + }, + { + "songId": 314, + "songName": "Castlewars", + "musicTabButtonId": 285, + "regionIds": [9520, 9620] + }, + { + "songId": 481, + "songName": "Catch Me If You Can", + "musicTabButtonId": 379, + "regionIds": [10646] + }, + { + "songId": 325, + "songName": "Cave Background", + "musicTabButtonId": 50, + "regionIds": [12185, 11929, 12184] + }, + { + "songId": 357, + "songName": "Cave of Beasts", + "musicTabButtonId": 311, + "regionIds": [11165] + }, + { + "songId": 389, + "songName": "Cave of The Goblins", + "musicTabButtonId": 313, + "regionIds": [12949, 12693] + }, + { + "songId": 68, + "songName": "Cavern", + "musicTabButtonId": 51, + "regionIds": [10388, 10389, 12193] + }, + { + "songId": 330, + "songName": "Cellar Song", + "musicTabButtonId": 197, + "regionIds": [12697] + }, + { + "songId": 63, + "songName": "Chain of Command", + "musicTabButtonId": 52, + "regionIds": [10905, 10651, 10648, 10649, 10650] + }, + { + "songId": 282, + "songName": "Chamber", + "musicTabButtonId": 291, + "regionIds": [11078, 10821] + }, + { + "songId": 583, + "songName": "Chef Surprise", + "musicTabButtonId": 406, + "regionIds": [0] + }, + { + "songId": 575, + "songName": "Chickened Out", + "musicTabButtonId": 405, + "regionIds": [9796] + }, + { + "songId": 71, + "songName": "Chompy Hunt", + "musicTabButtonId": 202, + "regionIds": [10542, 10642] + }, + { + "songId": 383, + "songName": "City of The Dead", + "musicTabButtonId": 327, + "regionIds": [12844, 12843, 13099] + }, + { + "songId": 373, + "songName": "Claustrophobia", + "musicTabButtonId": 316, + "regionIds": [9549, 9293] + }, + { + "songId": 67, + "songName": "Close Quarters", + "musicTabButtonId": 199, + "regionIds": [12602] + }, + { + "songId": 269, + "songName": "Competition", + "musicTabButtonId": 254, + "regionIds": [8781] + }, + { + "songId": 142, + "songName": "Complication", + "musicTabButtonId": 270, + "regionIds": [9035] + }, + { + "songId": 258, + "songName": "Contest", + "musicTabButtonId": 222, + "regionIds": [11576] + }, + { + "songId": 418, + "songName": "Corporal Punishment", + "musicTabButtonId": 370, + "regionIds": [12619] + }, + { + "songId": 509, + "songName": "Corridors of Power", + "musicTabButtonId": 423, + "regionIds": [0] + }, + { + "songId": 178, + "songName": "Courage", + "musicTabButtonId": 256, + "regionIds": [11673, 11674] + }, + { + "songId": 259, + "songName": "Crystal Castle", + "musicTabButtonId": 231, + "regionIds": [9011, 9012] + }, + { + "songId": 181, + "songName": "Crystal Cave", + "musicTabButtonId": 53, + "regionIds": [9797] + }, + { + "songId": 169, + "songName": "Crystal Sword", + "musicTabButtonId": 54, + "regionIds": [12855, 10647] + }, + { + "songId": 59, + "songName": "Cursed", + "musicTabButtonId": 205, + "regionIds": [9879, 9623] + }, + { + "songId": 198, + "songName": "Dagannoth Dawn", + "musicTabButtonId": 374, + "regionIds": [7748, 7236] + }, + { + "songId": 560, + "songName": "Dance of Death", + "musicTabButtonId": 436, + "regionIds": [0] + }, + { + "songId": 380, + "songName": "Dance of The Undead", + "musicTabButtonId": 334, + "regionIds": [14131] + }, + { + "songId": 336, + "songName": "Dangerous Road", + "musicTabButtonId": 264, + "regionIds": [11413] + }, + { + "songId": 381, + "songName": "Dangerous Way", + "musicTabButtonId": 335, + "regionIds": [14231] + }, + { + "songId": 182, + "songName": "Dangerous", + "musicTabButtonId": 55, + "regionIds": [12343, 13115, 13371] + }, + { + "songId": 326, + "songName": "Dark", + "musicTabButtonId": 56, + "regionIds": [13113, 13369] + }, + { + "songId": 576, + "songName": "Davy Jones Locker", + "musicTabButtonId": 404, + "regionIds": [11924] + }, + { + "songId": 476, + "songName": "Dead Can Dance", + "musicTabButtonId": 359, + "regionIds": [12601] + }, + { + "songId": 84, + "songName": "Dead Quiet", + "musicTabButtonId": 216, + "regionIds": [13621, 9294, 9550] + }, + { + "songId": 288, + "songName": "Deadlands", + "musicTabButtonId": 246, + "regionIds": [14134, 14390] + }, + { + "songId": 278, + "songName": "Deep Down", + "musicTabButtonId": 290, + "regionIds": [11079, 10822, 10823] + }, + { + "songId": 37, + "songName": "Deep Wildy", + "musicTabButtonId": 57, + "regionIds": [11835, 11836] + }, + { + "songId": 465, + "songName": "Desert Heat", + "musicTabButtonId": 385, + "regionIds": [13615, 13614] + }, + { + "songId": 174, + "songName": "Desert Voyage", + "musicTabButtonId": 58, + "regionIds": [13103, 13359, 13102] + }, + { + "songId": 532, + "songName": "Diango's Little Helpers", + "musicTabButtonId": 392, + "regionIds": [8005] + }, + { + "songId": 86, + "songName": "Dimension X", + "musicTabButtonId": 442, + "regionIds": [0] + }, + { + "songId": 501, + "songName": "Distant Land", + "musicTabButtonId": 409, + "regionIds": [13874, 14130, 13873, 14129] + }, + { + "songId": 610, + "songName": "Distillery Hilarity", + "musicTabButtonId": 432, + "regionIds": [0] + }, + { + "songId": 537, + "songName": "Dogs of War", + "musicTabButtonId": 437, + "regionIds": [0] + }, + { + "songId": 56, + "songName": "Doorways", + "musicTabButtonId": 59, + "regionIds": [12598] + }, + { + "songId": 361, + "songName": "Down Below", + "musicTabButtonId": 326, + "regionIds": [12439, 12438] + }, + { + "songId": 143, + "songName": "Down To Earth", + "musicTabButtonId": 255, + "regionIds": [10571] + }, + { + "songId": 358, + "songName": "Dragontooth Island", + "musicTabButtonId": 309, + "regionIds": [15159] + }, + { + "songId": 327, + "songName": "Dream", + "musicTabButtonId": 60, + "regionIds": [12594] + }, + { + "songId": 623, + "songName": "Dreamstate", + "musicTabButtonId": 446, + "regionIds": [0] + }, + { + "songId": 47, + "songName": "Duel Arena", + "musicTabButtonId": 189, + "regionIds": [13362] + }, + { + "songId": 173, + "songName": "Dunjun", + "musicTabButtonId": 61, + "regionIds": [11928, 11672] + }, + { + "songId": 351, + "songName": "Dynasty", + "musicTabButtonId": 317, + "regionIds": [13358] + }, + { + "songId": 69, + "songName": "Egypt", + "musicTabButtonId": 62, + "regionIds": [13104, 13360] + }, + { + "songId": 252, + "songName": "Elven Mist", + "musicTabButtonId": 239, + "regionIds": [9266] + }, + { + "songId": 148, + "songName": "Emotion", + "musicTabButtonId": 63, + "regionIds": [10033, 10133, 10309, 11081] + }, + { + "songId": 138, + "songName": "Emperor", + "musicTabButtonId": 179, + "regionIds": [11570, 11670] + }, + { + "songId": 17, + "songName": "Escape", + "musicTabButtonId": 198, + "regionIds": [10903] + }, + { + "songId": 285, + "songName": "Etceteria", + "musicTabButtonId": 273, + "regionIds": [10300] + }, + { + "songId": 586, + "songName": "Everlasting Fire", + "musicTabButtonId": 418, + "regionIds": [13373] + }, + { + "songId": 268, + "songName": "Everywhere", + "musicTabButtonId": 236, + "regionIds": [8499, 8755] + }, + { + "songId": 411, + "songName": "Evil Bob's Island", + "musicTabButtonId": 358, + "regionIds": [10058] + }, + { + "songId": 106, + "songName": "Expanse", + "musicTabButtonId": 64, + "regionIds": [12852, 12605, 12952] + }, + { + "songId": 41, + "songName": "Expecting", + "musicTabButtonId": 65, + "regionIds": [9522, 9778, 9878] + }, + { + "songId": 153, + "songName": "Expedition", + "musicTabButtonId": 175, + "regionIds": [11676, 9619] + }, + { + "songId": 270, + "songName": "Exposed", + "musicTabButtonId": 232, + "regionIds": [8752] + }, + { + "songId": 118, + "songName": "Faerie", + "musicTabButtonId": 66, + "regionIds": [9541, 9540] + }, + { + "songId": 337, + "songName": "Faithless", + "musicTabButtonId": 265, + "regionIds": [12856, 13112] + }, + { + "songId": 72, + "songName": "Fanfare", + "musicTabButtonId": 67, + "regionIds": [11828] + }, + { + "songId": 166, + "songName": "Fanfare2", + "musicTabButtonId": 68, + "regionIds": [11823] + }, + { + "songId": 167, + "songName": "Fanfare3", + "musicTabButtonId": 69, + "regionIds": [10545] + }, + { + "songId": 504, + "songName": "Fangs For The Memory", + "musicTabButtonId": 410, + "regionIds": [0] + }, + { + "songId": 372, + "songName": "Far Away", + "musicTabButtonId": 348, + "regionIds": [9265] + }, + { + "songId": 602, + "songName": "Fear And Loathing", + "musicTabButtonId": 411, + "regionIds": [0] + }, + { + "songId": 344, + "songName": "Fenkenstrain's Refrain", + "musicTabButtonId": 303, + "regionIds": [13879, 14135] + }, + { + "songId": 375, + "songName": "Fight Or Flight", + "musicTabButtonId": 349, + "regionIds": [8008, 7752] + }, + { + "songId": 312, + "songName": "Find My Way", + "musicTabButtonId": 284, + "regionIds": [10894, 11150] + }, + { + "songId": 463, + "songName": "Fire And Brimstone", + "musicTabButtonId": 365, + "regionIds": [9552] + }, + { + "songId": 119, + "songName": "Fishing", + "musicTabButtonId": 70, + "regionIds": [11317] + }, + { + "songId": 163, + "songName": "Flute Salad", + "musicTabButtonId": 71, + "regionIds": [12595] + }, + { + "songId": 558, + "songName": "Food For Thought", + "musicTabButtonId": 438, + "regionIds": [0] + }, + { + "songId": 121, + "songName": "Forbidden", + "musicTabButtonId": 204, + "regionIds": [13111, 13367] + }, + { + "songId": 251, + "songName": "Forest", + "musicTabButtonId": 238, + "regionIds": [9009] + }, + { + "songId": 98, + "songName": "Forever", + "musicTabButtonId": 72, + "regionIds": [12342, 12444, 12443, 12442] + }, + { + "songId": 436, + "songName": "Forgettable Melody", + "musicTabButtonId": 350, + "regionIds": [7501] + }, + { + "songId": 378, + "songName": "Forgotten", + "musicTabButtonId": 320, + "regionIds": [10828] + }, + { + "songId": 409, + "songName": "Frogland", + "musicTabButtonId": 355, + "regionIds": [9802] + }, + { + "songId": 294, + "songName": "Frostbite", + "musicTabButtonId": 325, + "regionIds": [11323, 11579] + }, + { + "songId": 347, + "songName": "Fruits De Mer", + "musicTabButtonId": 272, + "regionIds": [11059] + }, + { + "songId": 603, + "songName": "Funny Bunnies", + "musicTabButtonId": 415, + "regionIds": [9810] + }, + { + "songId": 159, + "songName": "Gaol", + "musicTabButtonId": 73, + "regionIds": [10031, 12090, 10131] + }, + { + "songId": 125, + "songName": "Garden", + "musicTabButtonId": 74, + "regionIds": [12853, 12953] + }, + { + "songId": 22, + "songName": "Gnome King", + "musicTabButtonId": 75, + "regionIds": [9782, 9783] + }, + { + "songId": 150, + "songName": "Gnome Theme", + "musicTabButtonId": 76, + "regionIds": [12085] + }, + { + "songId": 33, + "songName": "Gnome Village", + "musicTabButtonId": 77, + "regionIds": [9781] + }, + { + "songId": 101, + "songName": "Gnome Village2", + "musicTabButtonId": 78, + "regionIds": [9269, 9525] + }, + { + "songId": 23, + "songName": "Gnome", + "musicTabButtonId": 79, + "regionIds": [11830] + }, + { + "songId": 112, + "songName": "Gnomeball", + "musicTabButtonId": 80, + "regionIds": [9270, 9526, 9271, 9527] + }, + { + "songId": 346, + "songName": "Goblin Game", + "musicTabButtonId": 271, + "regionIds": [10393] + }, + { + "songId": 535, + "songName": "Golden Touch", + "musicTabButtonId": 394, + "regionIds": [0] + }, + { + "songId": 116, + "songName": "Greatness", + "musicTabButtonId": 81, + "regionIds": [12596] + }, + { + "songId": 520, + "songName": "Grip of The Talon", + "musicTabButtonId": 377, + "regionIds": [0] + }, + { + "songId": 246, + "songName": "Grotto", + "musicTabButtonId": 212, + "regionIds": [13720] + }, + { + "songId": 466, + "songName": "Ground Scape", + "musicTabButtonId": 347, + "regionIds": [0] + }, + { + "songId": 128, + "songName": "Grumpy", + "musicTabButtonId": 203, + "regionIds": [10286] + }, + { + "songId": 638, + "songName": "Ham Fisted", + "musicTabButtonId": 430, + "regionIds": [0] + }, + { + "songId": 76, + "songName": "Harmony", + "musicTabButtonId": 82, + "regionIds": [12850, 7507] + }, + { + "songId": 46, + "songName": "Harmony2", + "musicTabButtonId": 192, + "regionIds": [12950] + }, + { + "songId": 277, + "songName": "Haunted Mine", + "musicTabButtonId": 288, + "regionIds": [11077] + }, + { + "songId": 434, + "songName": "Have A Blast", + "musicTabButtonId": 362, + "regionIds": [7757] + }, + { + "songId": 612, + "songName": "Head To Head", + "musicTabButtonId": 421, + "regionIds": [0] + }, + { + "songId": 190, + "songName": "Heart And Mind", + "musicTabButtonId": 200, + "regionIds": [10059] + }, + { + "songId": 4, + "songName": "Hells Bells", + "musicTabButtonId": 293, + "regionIds": [11066, 11067] + }, + { + "songId": 97, + "songName": "Hermit", + "musicTabButtonId": 220, + "regionIds": [9034] + }, + { + "songId": 55, + "songName": "High Seas", + "musicTabButtonId": 83, + "regionIds": [11057] + }, + { + "songId": 205, + "songName": "High Spirits", + "musicTabButtonId": 459, + "regionIds": [0] + }, + { + "songId": 454, + "songName": "Home Sweet Home", + "musicTabButtonId": 428, + "regionIds": [0] + }, + { + "songId": 621, + "songName": "HomeScape", + "musicTabButtonId": 427, + "regionIds": [0] + }, + { + "songId": 18, + "songName": "Horizon", + "musicTabButtonId": 84, + "regionIds": [11573] + }, + { + "songId": 384, + "songName": "Hypnotized", + "musicTabButtonId": 330, + "regionIds": [0] + }, + { + "songId": 1, + "songName": "Iban", + "musicTabButtonId": 85, + "regionIds": [8519, 8520, 8521] + }, + { + "songId": 87, + "songName": "Ice Melody", + "musicTabButtonId": 190, + "regionIds": [11318] + }, + { + "songId": 370, + "songName": "In Between", + "musicTabButtonId": 315, + "regionIds": [10317, 10061] + }, + { + "songId": 530, + "songName": "In The Brine", + "musicTabButtonId": 401, + "regionIds": [14638] + }, + { + "songId": 511, + "songName": "In The Clink", + "musicTabButtonId": 397, + "regionIds": [8261] + }, + { + "songId": 188, + "songName": "In The Manor", + "musicTabButtonId": 86, + "regionIds": [10287] + }, + { + "songId": 469, + "songName": "In The Pits", + "musicTabButtonId": 366, + "regionIds": [9808] + }, + { + "songId": 519, + "songName": "Incantation", + "musicTabButtonId": 378, + "regionIds": [0] + }, + { + "songId": 260, + "songName": "Insect Queen", + "musicTabButtonId": 228, + "regionIds": [13972, 14228] + }, + { + "songId": 96, + "songName": "Inspiration", + "musicTabButtonId": 87, + "regionIds": [12087] + }, + { + "songId": 412, + "songName": "Into The Abyss", + "musicTabButtonId": 343, + "regionIds": [12108, 12107] + }, + { + "songId": 95, + "songName": "Intrepid", + "musicTabButtonId": 88, + "regionIds": [9369, 9370] + }, + { + "songId": 306, + "songName": "Island Life", + "musicTabButtonId": 280, + "regionIds": [10794, 11050] + }, + { + "songId": 627, + "songName": "Isle of Everywhere", + "musicTabButtonId": 448, + "regionIds": [0] + }, + { + "songId": 6, + "songName": "Jolly-R", + "musicTabButtonId": 89, + "regionIds": [11058] + }, + { + "songId": 172, + "songName": "Jungle Island", + "musicTabButtonId": 90, + "regionIds": [11309, 11313] + }, + { + "songId": 479, + "songName": "Jungle Troubles", + "musicTabButtonId": 363, + "regionIds": [11568, 10055] + }, + { + "songId": 114, + "songName": "Jungly 1", + "musicTabButtonId": 91, + "regionIds": [11054, 11154] + }, + { + "songId": 115, + "songName": "Jungly 2", + "musicTabButtonId": 92, + "regionIds": [10802] + }, + { + "songId": 117, + "songName": "Jungly 3", + "musicTabButtonId": 93, + "regionIds": [11055] + }, + { + "songId": 362, + "songName": "Karamja Jam", + "musicTabButtonId": 221, + "regionIds": [10900, 10899] + }, + { + "songId": 9, + "songName": "Kingdom", + "musicTabButtonId": 298, + "regionIds": [11319] + }, + { + "songId": 191, + "songName": "Knightly", + "musicTabButtonId": 94, + "regionIds": [10291] + }, + { + "songId": 134, + "songName": "La Mort", + "musicTabButtonId": 369, + "regionIds": [8779] + }, + { + "songId": 287, + "songName": "Lair", + "musicTabButtonId": 247, + "regionIds": [13975] + }, + { + "songId": 197, + "songName": "Lament of Meiyerditch", + "musicTabButtonId": 452, + "regionIds": [0] + }, + { + "songId": 542, + "songName": "Lament", + "musicTabButtonId": 399, + "regionIds": [12433] + }, + { + "songId": 506, + "songName": "Land Down Under", + "musicTabButtonId": 424, + "regionIds": [0] + }, + { + "songId": 396, + "songName": "Land of the Dwarves", + "musicTabButtonId": 342, + "regionIds": [11423] + }, + { + "songId": 164, + "songName": "Landlubber", + "musicTabButtonId": 194, + "regionIds": [10801] + }, + { + "songId": 546, + "songName": "Last Stand", + "musicTabButtonId": 419, + "regionIds": [0] + }, + { + "songId": 60, + "songName": "Lasting", + "musicTabButtonId": 95, + "regionIds": [10549] + }, + { + "songId": 293, + "songName": "Legend", + "musicTabButtonId": 241, + "regionIds": [10808, 11064] + }, + { + "songId": 66, + "songName": "Legion", + "musicTabButtonId": 96, + "regionIds": [10039, 10295, 12089] + }, + { + "songId": 631, + "songName": "Life's A Beach!", + "musicTabButtonId": 433, + "regionIds": [0] + }, + { + "songId": 320, + "songName": "Lighthouse", + "musicTabButtonId": 267, + "regionIds": [10040, 9799] + }, + { + "songId": 113, + "songName": "Lightness", + "musicTabButtonId": 97, + "regionIds": [12599] + }, + { + "songId": 74, + "songName": "Lightwalk", + "musicTabButtonId": 98, + "regionIds": [11061] + }, + { + "songId": 632, + "songName": "Little Cave of Horrors", + "musicTabButtonId": 434, + "regionIds": [0] + }, + { + "songId": 168, + "songName": "Lonesome", + "musicTabButtonId": 187, + "regionIds": [13203] + }, + { + "songId": 161, + "songName": "Long Ago", + "musicTabButtonId": 99, + "regionIds": [10544] + }, + { + "songId": 12, + "songName": "Long Way Home", + "musicTabButtonId": 100, + "regionIds": [11826] + }, + { + "songId": 253, + "songName": "Lost Soul", + "musicTabButtonId": 233, + "regionIds": [9008, 9264] + }, + { + "songId": 20, + "songName": "Lullaby", + "musicTabButtonId": 102, + "regionIds": [13365, 10551] + }, + { + "songId": 264, + "songName": "Mad Eadgar", + "musicTabButtonId": 225, + "regionIds": [11677] + }, + { + "songId": 13, + "songName": "Mage Arena", + "musicTabButtonId": 103, + "regionIds": [12348, 12349, 10057] + }, + { + "songId": 185, + "songName": "Magic Dance", + "musicTabButtonId": 104, + "regionIds": [10288] + }, + { + "songId": 184, + "songName": "Magical Journey", + "musicTabButtonId": 105, + "regionIds": [10805] + }, + { + "songId": 544, + "songName": "Making Waves", + "musicTabButtonId": 420, + "regionIds": [9272, 9528, 9273] + }, + { + "songId": 559, + "songName": "Malady", + "musicTabButtonId": 439, + "regionIds": [0] + }, + { + "songId": 328, + "songName": "March", + "musicTabButtonId": 101, + "regionIds": [10036] + }, + { + "songId": 304, + "songName": "Marooned", + "musicTabButtonId": 279, + "regionIds": [11562, 12117] + }, + { + "songId": 261, + "songName": "Marzipan", + "musicTabButtonId": 226, + "regionIds": [11421, 11167, 11166] + }, + { + "songId": 340, + "songName": "Masquerade", + "musicTabButtonId": 300, + "regionIds": [10908] + }, + { + "songId": 577, + "songName": "Mastermindless", + "musicTabButtonId": 407, + "regionIds": [0] + }, + { + "songId": 156, + "songName": "Mausoleum", + "musicTabButtonId": 209, + "regionIds": [13722] + }, + { + "songId": 508, + "songName": "Meddling Kids", + "musicTabButtonId": 425, + "regionIds": [0] + }, + { + "songId": 157, + "songName": "Medieval", + "musicTabButtonId": 106, + "regionIds": [13109] + }, + { + "songId": 193, + "songName": "Mellow", + "musicTabButtonId": 107, + "regionIds": [10293] + }, + { + "songId": 317, + "songName": "Melodrama", + "musicTabButtonId": 286, + "regionIds": [9776] + }, + { + "songId": 254, + "songName": "Meridian", + "musicTabButtonId": 234, + "regionIds": [8497, 8753, 9287] + }, + { + "songId": 600, + "songName": "Method of Madness", + "musicTabButtonId": 412, + "regionIds": [0] + }, + { + "songId": 107, + "songName": "Miles Away", + "musicTabButtonId": 108, + "regionIds": [11571, 10569] + }, + { + "songId": 534, + "songName": "Mind Over Matter", + "musicTabButtonId": 395, + "regionIds": [0] + }, + { + "songId": 65, + "songName": "Miracle Dance", + "musicTabButtonId": 109, + "regionIds": [11083] + }, + { + "songId": 388, + "songName": "Mirage", + "musicTabButtonId": 331, + "regionIds": [13199] + }, + { + "songId": 284, + "songName": "Miscellania", + "musicTabButtonId": 274, + "regionIds": [10044] + }, + { + "songId": 200, + "songName": "The Mollusc Menace", + "musicTabButtonId": 455, + "regionIds": [0] + }, + { + "songId": 21, + "songName": "Monarch Waltz", + "musicTabButtonId": 110, + "regionIds": [10807] + }, + { + "songId": 303, + "songName": "Monkey Madness", + "musicTabButtonId": 278, + "regionIds": [11051] + }, + { + "songId": 343, + "songName": "Monster Melee", + "musicTabButtonId": 310, + "regionIds": [12694] + }, + { + "songId": 10, + "songName": "Moody", + "musicTabButtonId": 111, + "regionIds": [9523, 9779, 12600] + }, + { + "songId": 48, + "songName": "Morytania", + "musicTabButtonId": 210, + "regionIds": [13622] + }, + { + "songId": 515, + "songName": "Mudskipper Melody", + "musicTabButtonId": 371, + "regionIds": [11824] + }, + { + "songId": 203, + "songName": "My Arm's Journey", + "musicTabButtonId": 457, + "regionIds": [0] + }, + { + "songId": 348, + "songName": "Narnode's Theme", + "musicTabButtonId": 275, + "regionIds": [9882] + }, + { + "songId": 245, + "songName": "Natural", + "musicTabButtonId": 213, + "regionIds": [13620, 9038] + }, + { + "songId": 155, + "songName": "Neverland", + "musicTabButtonId": 112, + "regionIds": [9780] + }, + { + "songId": 62, + "songName": "Newbie Melody", + "musicTabButtonId": 113, + "regionIds": [12080, 12336, 12592, 12079, 12335] + }, + { + "songId": 646, + "songName": "Night of The Vampyre", + "musicTabButtonId": 454, + "regionIds": [0] + }, + { + "songId": 127, + "songName": "Nightfall", + "musicTabButtonId": 114, + "regionIds": [11827, 12861] + }, + { + "songId": 594, + "songName": "No Way Out", + "musicTabButtonId": 413, + "regionIds": [0] + }, + { + "songId": 58, + "songName": "Nomad", + "musicTabButtonId": 201, + "regionIds": [11056] + }, + { + "songId": 587, + "songName": "Null And Void", + "musicTabButtonId": 416, + "regionIds": [10537] + }, + { + "songId": 633, + "songName": "On The Wing", + "musicTabButtonId": 440, + "regionIds": [0] + }, + { + "songId": 103, + "songName": "Oriental", + "musicTabButtonId": 115, + "regionIds": [11666, 11668] + }, + { + "songId": 322, + "songName": "Out of The Deep", + "musicTabButtonId": 268, + "regionIds": [10140, 10056] + }, + { + "songId": 447, + "songName": "Over To Nardah", + "musicTabButtonId": 387, + "regionIds": [13613] + }, + { + "songId": 256, + "songName": "Overpass", + "musicTabButtonId": 237, + "regionIds": [9267] + }, + { + "songId": 7, + "songName": "Overture", + "musicTabButtonId": 116, + "regionIds": [10806] + }, + { + "songId": 93, + "songName": "Parade", + "musicTabButtonId": 117, + "regionIds": [13110, 13366] + }, + { + "songId": 393, + "songName": "Path of Peril", + "musicTabButtonId": 323, + "regionIds": [10575, 10831] + }, + { + "songId": 364, + "songName": "Pathways", + "musicTabButtonId": 297, + "regionIds": [10901] + }, + { + "songId": 588, + "songName": "Pest Control", + "musicTabButtonId": 417, + "regionIds": [10536] + }, + { + "songId": 505, + "songName": "Pharaoh's Tomb", + "musicTabButtonId": 398, + "regionIds": [13356, 12105] + }, + { + "songId": 354, + "songName": "Phasmatys", + "musicTabButtonId": 307, + "regionIds": [14746] + }, + { + "songId": 419, + "songName": "Pheasant Peasant", + "musicTabButtonId": 354, + "regionIds": [10314] + }, + { + "songId": 614, + "songName": "Pinball Wizard", + "musicTabButtonId": 422, + "regionIds": [0] + }, + { + "songId": 149, + "songName": "Principality", + "musicTabButtonId": 219, + "regionIds": [11575] + }, + { + "songId": 334, + "songName": "Pirates of Peril", + "musicTabButtonId": 263, + "regionIds": [12093] + }, + { + "songId": 158, + "songName": "Quest", + "musicTabButtonId": 118, + "regionIds": [10315] + }, + { + "songId": 482, + "songName": "Rat A Tat Tat", + "musicTabButtonId": 382, + "regionIds": [11599] + }, + { + "songId": 491, + "songName": "Rat Hunt", + "musicTabButtonId": 383, + "regionIds": [11343] + }, + { + "songId": 318, + "songName": "Ready For Battle", + "musicTabButtonId": 287, + "regionIds": [0] + }, + { + "songId": 329, + "songName": "Regal", + "musicTabButtonId": 119, + "regionIds": [13117] + }, + { + "songId": 78, + "songName": "Reggae", + "musicTabButtonId": 120, + "regionIds": [11565, 11821] + }, + { + "songId": 89, + "songName": "Reggae2", + "musicTabButtonId": 121, + "regionIds": [11567] + }, + { + "songId": 289, + "songName": "Rellekka", + "musicTabButtonId": 259, + "regionIds": [10297, 10553, 10554] + }, + { + "songId": 44, + "songName": "Right On Track", + "musicTabButtonId": 351, + "regionIds": [7501] + }, + { + "songId": 262, + "songName": "Righteousness", + "musicTabButtonId": 227, + "regionIds": [9803] + }, + { + "songId": 91, + "songName": "Riverside", + "musicTabButtonId": 122, + "regionIds": [8496, 10803] + }, + { + "songId": 204, + "songName": "Roc and Roll", + "musicTabButtonId": 458, + "regionIds": [0] + }, + { + "songId": 533, + "songName": "Roll The Bones", + "musicTabButtonId": 396, + "regionIds": [0] + }, + { + "songId": 335, + "songName": "Romancing The Crone", + "musicTabButtonId": 294, + "regionIds": [11068] + }, + { + "songId": 390, + "songName": "Romper Chomper", + "musicTabButtonId": 338, + "regionIds": [9263, 9519] + }, + { + "songId": 53, + "songName": "Royale", + "musicTabButtonId": 123, + "regionIds": [11671] + }, + { + "songId": 57, + "songName": "Rune Essence", + "musicTabButtonId": 124, + "regionIds": [11595] + }, + { + "songId": 5, + "songName": "Sad Meadow", + "musicTabButtonId": 125, + "regionIds": [10035] + }, + { + "songId": 290, + "songName": "Saga", + "musicTabButtonId": 240, + "regionIds": [10296, 10552] + }, + { + "songId": 359, + "songName": "Sarcophagus", + "musicTabButtonId": 324, + "regionIds": [12945] + }, + { + "songId": 490, + "songName": "Sarim's Vermin", + "musicTabButtonId": 384, + "regionIds": [11926] + }, + { + "songId": 144, + "songName": "Scape Cave", + "musicTabButtonId": 126, + "regionIds": [12436, 12698, 13210, 12954] + }, + { + "songId": 0, + "songName": "Scape Main", + "musicTabButtonId": 318, + "regionIds": [0] + }, + { + "songId": 400, + "songName": "Scape Original", + "musicTabButtonId": 127, + "regionIds": [0] + }, + { + "songId": 331, + "songName": "Scape Sad", + "musicTabButtonId": 128, + "regionIds": [13116, 13372] + }, + { + "songId": 547, + "songName": "Scape Santa", + "musicTabButtonId": 292, + "regionIds": [0] + }, + { + "songId": 321, + "songName": "Scape Scared", + "musicTabButtonId": 262, + "regionIds": [0] + }, + { + "songId": 54, + "songName": "Scape Soft", + "musicTabButtonId": 184, + "regionIds": [11829] + }, + { + "songId": 332, + "songName": "Scape Wild", + "musicTabButtonId": 129, + "regionIds": [12857, 12604, 12860] + }, + { + "songId": 352, + "songName": "Scarab", + "musicTabButtonId": 328, + "regionIds": [12589, 12845, 13101, 11085, 11341, 11597] + }, + { + "songId": 35, + "songName": "Sea Shanty 2", + "musicTabButtonId": 131, + "regionIds": [12082] + }, + { + "songId": 92, + "songName": "Sea Shanty", + "musicTabButtonId": 130, + "regionIds": [11569] + }, + { + "songId": 110, + "songName": "Serenade", + "musicTabButtonId": 132, + "regionIds": [9521, 9777] + }, + { + "songId": 52, + "songName": "Serene", + "musicTabButtonId": 133, + "regionIds": [11936, 11937, 11339, 11837] + }, + { + "songId": 356, + "songName": "Settlement", + "musicTabButtonId": 312, + "regionIds": [11065] + }, + { + "songId": 286, + "songName": "Shadowland", + "musicTabButtonId": 249, + "regionIds": [13618, 13875, 8526] + }, + { + "songId": 122, + "songName": "Shine", + "musicTabButtonId": 134, + "regionIds": [13363] + }, + { + "songId": 120, + "songName": "Shining", + "musicTabButtonId": 186, + "regionIds": [12858] + }, + { + "songId": 353, + "songName": "Shipwrecked", + "musicTabButtonId": 306, + "regionIds": [14391] + }, + { + "songId": 311, + "songName": "Showdown", + "musicTabButtonId": 283, + "regionIds": [10895] + }, + { + "songId": 640, + "songName": "Sigmund's Showdown", + "musicTabButtonId": 431, + "regionIds": [0] + }, + { + "songId": 257, + "songName": "Sojourn", + "musicTabButtonId": 224, + "regionIds": [11321, 11577] + }, + { + "songId": 80, + "songName": "Soundscape", + "musicTabButtonId": 135, + "regionIds": [9774, 10030] + }, + { + "songId": 387, + "songName": "Sphinx", + "musicTabButtonId": 329, + "regionIds": [13100] + }, + { + "songId": 175, + "songName": "Spirit", + "musicTabButtonId": 136, + "regionIds": [12597] + }, + { + "songId": 462, + "songName": "Spirits of The Elid", + "musicTabButtonId": 388, + "regionIds": [13461] + }, + { + "songId": 77, + "songName": "Splendour", + "musicTabButtonId": 137, + "regionIds": [11574] + }, + { + "songId": 129, + "songName": "Spooky Jungle", + "musicTabButtonId": 139, + "regionIds": [11053] + }, + { + "songId": 333, + "songName": "Spooky", + "musicTabButtonId": 138, + "regionIds": [12340] + }, + { + "songId": 11, + "songName": "Spooky2", + "musicTabButtonId": 289, + "regionIds": [13718, 13974] + }, + { + "songId": 241, + "songName": "Stagnant", + "musicTabButtonId": 215, + "regionIds": [13876, 8782] + }, + { + "songId": 108, + "songName": "Starlight", + "musicTabButtonId": 140, + "regionIds": [12181, 11925] + }, + { + "songId": 151, + "songName": "Start", + "musicTabButtonId": 172, + "regionIds": [12339] + }, + { + "songId": 111, + "songName": "Still Night", + "musicTabButtonId": 141, + "regionIds": [13108] + }, + { + "songId": 319, + "songName": "Stillness", + "musicTabButtonId": 296, + "regionIds": [13977] + }, + { + "songId": 292, + "songName": "Stranded", + "musicTabButtonId": 295, + "regionIds": [11322, 11578] + }, + { + "songId": 470, + "songName": "Strange Place", + "musicTabButtonId": 364, + "regionIds": [7494] + }, + { + "songId": 243, + "songName": "Stratosphere", + "musicTabButtonId": 207, + "regionIds": [8523] + }, + { + "songId": 568, + "songName": "Storm Brew", + "musicTabButtonId": 402, + "regionIds": [10577] + }, + { + "songId": 517, + "songName": "Subterranea", + "musicTabButtonId": 375, + "regionIds": [10142, 10398] + }, + { + "songId": 267, + "songName": "Sunburn", + "musicTabButtonId": 242, + "regionIds": [12846, 13357] + }, + { + "songId": 265, + "songName": "Superstition", + "musicTabButtonId": 257, + "regionIds": [11153] + }, + { + "songId": 308, + "songName": "Suspicious", + "musicTabButtonId": 282, + "regionIds": [10567, 10311] + }, + { + "songId": 395, + "songName": "Tale of Keldagrim", + "musicTabButtonId": 341, + "regionIds": [11678, 11679] + }, + { + "songId": 140, + "songName": "Talking Forest", + "musicTabButtonId": 173, + "regionIds": [10550] + }, + { + "songId": 397, + "songName": "Tears of Guthix", + "musicTabButtonId": 332, + "regionIds": [12948] + }, + { + "songId": 296, + "songName": "Technology", + "musicTabButtonId": 277, + "regionIds": [10566, 10310, 9626] + }, + { + "songId": 376, + "songName": "Temple of Light", + "musicTabButtonId": 368, + "regionIds": [7496] + }, + { + "songId": 307, + "songName": "Temple", + "musicTabButtonId": 281, + "regionIds": [11151] + }, + { + "songId": 478, + "songName": "The Cellar Dwellers", + "musicTabButtonId": 361, + "regionIds": [10135, 10391] + }, + { + "songId": 425, + "songName": "The Chosen", + "musicTabButtonId": 346, + "regionIds": [9805] + }, + { + "songId": 79, + "songName": "The Desert", + "musicTabButtonId": 142, + "regionIds": [12591, 12847] + }, + { + "songId": 461, + "songName": "The Desolate Isle", + "musicTabButtonId": 352, + "regionIds": [10042] + }, + { + "songId": 541, + "songName": "The Enchanter", + "musicTabButtonId": 393, + "regionIds": [13462] + }, + { + "songId": 403, + "songName": "The Far Side", + "musicTabButtonId": 345, + "regionIds": [12111] + }, + { + "songId": 630, + "songName": "The Galleon", + "musicTabButtonId": 450, + "regionIds": [0] + }, + { + "songId": 464, + "songName": "The Genie", + "musicTabButtonId": 386, + "regionIds": [13457] + }, + { + "songId": 377, + "songName": "The Golem", + "musicTabButtonId": 319, + "regionIds": [13616, 13872] + }, + { + "songId": 643, + "songName": "The Last Shanty", + "musicTabButtonId": 453, + "regionIds": [0] + }, + { + "songId": 407, + "songName": "The Lost Melody", + "musicTabButtonId": 339, + "regionIds": [13206] + }, + { + "songId": 420, + "songName": "The Lost Tribe", + "musicTabButtonId": 340, + "regionIds": [0] + }, + { + "songId": 625, + "songName": "The Lunar Isle", + "musicTabButtonId": 447, + "regionIds": [0] + }, + { + "songId": 573, + "songName": "The Mad Mole", + "musicTabButtonId": 403, + "regionIds": [6992, 6993] + }, + { + "songId": 448, + "songName": "The Monsters Below", + "musicTabButtonId": 353, + "regionIds": [9886] + }, + { + "songId": 316, + "songName": "The Navigator", + "musicTabButtonId": 261, + "regionIds": [0] + }, + { + "songId": 485, + "songName": "The Noble Rodent", + "musicTabButtonId": 381, + "regionIds": [0] + }, + { + "songId": 355, + "songName": "The Other Side", + "musicTabButtonId": 308, + "regionIds": [14646, 14647] + }, + { + "songId": 398, + "songName": "The Power of Tears", + "musicTabButtonId": 333, + "regionIds": [0] + }, + { + "songId": 202, + "songName": "Prime Time", + "musicTabButtonId": 456, + "regionIds": [0] + }, + { + "songId": 413, + "songName": "The Quizmaster", + "musicTabButtonId": 356, + "regionIds": [7754] + }, + { + "songId": 402, + "songName": "The Rogues Den", + "musicTabButtonId": 344, + "regionIds": [11855, 11854, 12110, 12109] + }, + { + "songId": 170, + "songName": "The Shadow", + "musicTabButtonId": 143, + "regionIds": [11314, 11315] + }, + { + "songId": 341, + "songName": "The Slayer", + "musicTabButtonId": 302, + "regionIds": [11164] + }, + { + "songId": 510, + "songName": "Slither and Thither", + "musicTabButtonId": 426, + "regionIds": [0] + }, + { + "songId": 201, + "songName": "Slug a bug Ball", + "musicTabButtonId": 266, + "regionIds": [0] + }, + { + "songId": 339, + "songName": "The Terrible Tower", + "musicTabButtonId": 301, + "regionIds": [13623] + }, + { + "songId": 133, + "songName": "The Tower", + "musicTabButtonId": 144, + "regionIds": [10292, 10136, 10392] + }, + { + "songId": 109, + "songName": "Theme", + "musicTabButtonId": 174, + "regionIds": [10294, 10138, 10394] + }, + { + "songId": 379, + "songName": "Throne of The Demon", + "musicTabButtonId": 321, + "regionIds": [0] + }, + { + "songId": 242, + "songName": "Time Out", + "musicTabButtonId": 218, + "regionIds": [11591] + }, + { + "songId": 369, + "songName": "Time To Mine", + "musicTabButtonId": 314, + "regionIds": [11422] + }, + { + "songId": 338, + "songName": "Tiptoe", + "musicTabButtonId": 269, + "regionIds": [12440] + }, + { + "songId": 525, + "songName": "Title Fight", + "musicTabButtonId": 389, + "regionIds": [12696] + }, + { + "songId": 591, + "songName": "Tomb Raider", + "musicTabButtonId": 444, + "regionIds": [0] + }, + { + "songId": 105, + "songName": "Tomorrow", + "musicTabButtonId": 188, + "regionIds": [12081] + }, + { + "songId": 582, + "songName": "Too Many Cooks...", + "musicTabButtonId": 408, + "regionIds": [11930] + }, + { + "songId": 51, + "songName": "Trawler Minor", + "musicTabButtonId": 146, + "regionIds": [7755, 8011] + }, + { + "songId": 38, + "songName": "Trawler", + "musicTabButtonId": 145, + "regionIds": [7499, 8012] + }, + { + "songId": 130, + "songName": "Tree Spirits", + "musicTabButtonId": 147, + "regionIds": [9268, 9524] + }, + { + "songId": 187, + "songName": "Tremble", + "musicTabButtonId": 223, + "regionIds": [11320] + }, + { + "songId": 94, + "songName": "Tribal 2", + "musicTabButtonId": 150, + "regionIds": [11566, 11822] + }, + { + "songId": 162, + "songName": "Tribal Background", + "musicTabButtonId": 148, + "regionIds": [11312, 11412] + }, + { + "songId": 165, + "songName": "Tribal", + "musicTabButtonId": 149, + "regionIds": [11311] + }, + { + "songId": 192, + "songName": "Trinity", + "musicTabButtonId": 151, + "regionIds": [10804, 10904] + }, + { + "songId": 611, + "songName": "Trouble Brewing", + "musicTabButtonId": 435, + "regionIds": [0] + }, + { + "songId": 183, + "songName": "Troubled", + "musicTabButtonId": 152, + "regionIds": [11833] + }, + { + "songId": 88, + "songName": "Twilight", + "musicTabButtonId": 208, + "regionIds": [10906] + }, + { + "songId": 473, + "songName": "Tzhaar!", + "musicTabButtonId": 367, + "regionIds": [9551] + }, + { + "songId": 176, + "songName": "Undercurrent", + "musicTabButtonId": 195, + "regionIds": [12345] + }, + { + "songId": 179, + "songName": "Underground", + "musicTabButtonId": 153, + "regionIds": [13368, 11416] + }, + { + "songId": 323, + "songName": "Underground Pass", + "musicTabButtonId": 157, + "regionIds": [9622, 9621] + }, + { + "songId": 131, + "songName": "Understanding", + "musicTabButtonId": 206, + "regionIds": [9547] + }, + { + "songId": 3, + "songName": "Unknown Land", + "musicTabButtonId": 156, + "regionIds": [12338, 8524] + }, + { + "songId": 70, + "songName": "Upcoming", + "musicTabButtonId": 158, + "regionIds": [10546] + }, + { + "songId": 75, + "songName": "Venture", + "musicTabButtonId": 159, + "regionIds": [13364] + }, + { + "songId": 45, + "songName": "Venture2", + "musicTabButtonId": 193, + "regionIds": [13465, 13464] + }, + { + "songId": 528, + "songName": "Victory Is Mine", + "musicTabButtonId": 390, + "regionIds": [0] + }, + { + "songId": 61, + "songName": "Village", + "musicTabButtonId": 211, + "regionIds": [13878] + }, + { + "songId": 85, + "songName": "Vision", + "musicTabButtonId": 160, + "regionIds": [12337, 12437] + }, + { + "songId": 30, + "songName": "Voodoo Cult", + "musicTabButtonId": 161, + "regionIds": [11665, 9545] + }, + { + "songId": 32, + "songName": "Voyage", + "musicTabButtonId": 162, + "regionIds": [10038] + }, + { + "songId": 622, + "songName": "Waking Dream", + "musicTabButtonId": 445, + "regionIds": [0] + }, + { + "songId": 49, + "songName": "Wander", + "musicTabButtonId": 163, + "regionIds": [12083] + }, + { + "songId": 295, + "songName": "Warrior", + "musicTabButtonId": 260, + "regionIds": [10653] + }, + { + "songId": 634, + "songName": "Warriors' Guild", + "musicTabButtonId": 429, + "regionIds": [0] + }, + { + "songId": 82, + "songName": "Waterfall", + "musicTabButtonId": 164, + "regionIds": [10037, 10137] + }, + { + "songId": 244, + "songName": "Waterlogged", + "musicTabButtonId": 214, + "regionIds": [13877, 14133, 8014, 8270] + }, + { + "songId": 626, + "songName": "Way of The Enchanter", + "musicTabButtonId": 449, + "regionIds": [0] + }, + { + "songId": 394, + "songName": "Wayward", + "musicTabButtonId": 336, + "regionIds": [9875] + }, + { + "songId": 126, + "songName": "We Are The Fairies", + "musicTabButtonId": 441, + "regionIds": [0] + }, + { + "songId": 271, + "songName": "Well of Voyage", + "musicTabButtonId": 230, + "regionIds": [9366] + }, + { + "songId": 475, + "songName": "Wild Side", + "musicTabButtonId": 360, + "regionIds": [12092, 12348] + }, + { + "songId": 435, + "songName": "Wilderness", + "musicTabButtonId": 165, + "regionIds": [11832, 12346] + }, + { + "songId": 42, + "songName": "Wilderness2", + "musicTabButtonId": 166, + "regionIds": [12091, 12347] + }, + { + "songId": 43, + "songName": "Wilderness3", + "musicTabButtonId": 167, + "regionIds": [11834] + }, + { + "songId": 8, + "songName": "Wildwood", + "musicTabButtonId": 250, + "regionIds": [12344] + }, + { + "songId": 14, + "songName": "Witching", + "musicTabButtonId": 168, + "regionIds": [13114, 13370] + }, + { + "songId": 529, + "songName": "Woe of The Wyvern", + "musicTabButtonId": 391, + "regionIds": [0] + }, + { + "songId": 189, + "songName": "Wolf Mountain", + "musicTabButtonId": 191, + "regionIds": [12603, 12859] + }, + { + "songId": 34, + "songName": "Wonder", + "musicTabButtonId": 169, + "regionIds": [11831] + }, + { + "songId": 81, + "songName": "Wonderous", + "musicTabButtonId": 170, + "regionIds": [10548] + }, + { + "songId": 255, + "songName": "Woodland", + "musicTabButtonId": 235, + "regionIds": [8498, 8754] + }, + { + "songId": 15, + "songName": "Workshop", + "musicTabButtonId": 171, + "regionIds": [12084] + }, + { + "songId": 565, + "songName": "Wrath And Ruin", + "musicTabButtonId": 414, + "regionIds": [0] + }, + { + "songId": 524, + "songName": "Xenophobe", + "musicTabButtonId": 376, + "regionIds": [7492, 11589] + }, + { + "songId": 145, + "songName": "Yesteryear", + "musicTabButtonId": 185, + "regionIds": [12849] + }, + { + "songId": 146, + "songName": "Zealot", + "musicTabButtonId": 196, + "regionIds": [10827] + }, + { + "songId": 392, + "songName": "Zogre Dance", + "musicTabButtonId": 337, + "regionIds": [9775] + } + ] } diff --git a/data/config/npc-spawns/ardougne/guards.json b/data/config/npc-spawns/ardougne/guards.json index b6a88862a..8763224b5 100644 --- a/data/config/npc-spawns/ardougne/guards.json +++ b/data/config/npc-spawns/ardougne/guards.json @@ -1,65 +1,65 @@ [ - { - "npc": "rs:guard:2", - "spawn_x": 2635, - "spawn_y": 3339, - "movement_radius": 5, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2636, - "spawn_y": 3340, - "movement_radius": 5, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2637, - "spawn_y": 3339, - "movement_radius": 5, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2651, - "spawn_y": 3307, - "movement_radius": 10, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2659, - "spawn_y": 3309, - "movement_radius": 10, - "face": "WEST" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2661, - "spawn_y": 3309, - "movement_radius": 10, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2663, - "spawn_y": 3301, - "movement_radius": 10, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2665, - "spawn_y": 3300, - "movement_radius": 10, - "face": "NORTH" - }, - { - "npc": "rs:guard:2", - "spawn_x": 2664, - "spawn_y": 3318, - "movement_radius": 10, - "face": "NORTH" - } + { + "npc": "rs:guard:2", + "spawn_x": 2635, + "spawn_y": 3339, + "movement_radius": 5, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2636, + "spawn_y": 3340, + "movement_radius": 5, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2637, + "spawn_y": 3339, + "movement_radius": 5, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2651, + "spawn_y": 3307, + "movement_radius": 10, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2659, + "spawn_y": 3309, + "movement_radius": 10, + "face": "WEST" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2661, + "spawn_y": 3309, + "movement_radius": 10, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2663, + "spawn_y": 3301, + "movement_radius": 10, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2665, + "spawn_y": 3300, + "movement_radius": 10, + "face": "NORTH" + }, + { + "npc": "rs:guard:2", + "spawn_x": 2664, + "spawn_y": 3318, + "movement_radius": 10, + "face": "NORTH" + } ] diff --git a/data/config/npc-spawns/falador/guards.json b/data/config/npc-spawns/falador/guards.json index f2c0b3310..20492c6fb 100644 --- a/data/config/npc-spawns/falador/guards.json +++ b/data/config/npc-spawns/falador/guards.json @@ -1,23 +1,23 @@ [ - { - "npc": "rs:guard:0", - "spawn_x": 2967, - "spawn_y": 3388, - "movement_radius": 5, - "face": "NORTH" - }, - { - "npc": "rs:guard:0", - "spawn_x": 2965, - "spawn_y": 3383, - "movement_radius": 5, - "face": "NORTH" - }, - { - "npc": "rs:guard:1", - "spawn_x": 2968, - "spawn_y": 3377, - "movement_radius": 5, - "face": "NORTH" - } + { + "npc": "rs:guard:0", + "spawn_x": 2967, + "spawn_y": 3388, + "movement_radius": 5, + "face": "NORTH" + }, + { + "npc": "rs:guard:0", + "spawn_x": 2965, + "spawn_y": 3383, + "movement_radius": 5, + "face": "NORTH" + }, + { + "npc": "rs:guard:1", + "spawn_x": 2968, + "spawn_y": 3377, + "movement_radius": 5, + "face": "NORTH" + } ] diff --git a/data/config/npc-spawns/pestcontrol/bankers.json b/data/config/npc-spawns/pestcontrol/bankers.json index f47822cb0..6a2893d67 100644 --- a/data/config/npc-spawns/pestcontrol/bankers.json +++ b/data/config/npc-spawns/pestcontrol/bankers.json @@ -27,5 +27,4 @@ "movement_radius": 0, "face": "NORTH" } - -] \ No newline at end of file +] diff --git a/data/config/npcs/ardougne.json b/data/config/npcs/ardougne.json index b1dcddbec..18e33b693 100644 --- a/data/config/npcs/ardougne.json +++ b/data/config/npcs/ardougne.json @@ -2,24 +2,24 @@ "rs:ardougne_baker": { "variations": [ { - "suffix": 0, - "game_id": 571 + "suffix": 0, + "game_id": 571 }, { - "suffix": 1, - "game_id": 571 + "suffix": 1, + "game_id": 571 } ] }, "rs:knight": { "variations": [ { - "suffix": 0, - "game_id": 23 + "suffix": 0, + "game_id": 23 }, { - "suffix": 1, - "game_id": 26 + "suffix": 1, + "game_id": 26 } ] }, diff --git a/data/config/npcs/general.json b/data/config/npcs/general.json index c2fb0ff6e..7166e226a 100644 --- a/data/config/npcs/general.json +++ b/data/config/npcs/general.json @@ -2,7 +2,10 @@ "rs:rat": { "game_id": 47, "drop_table": [ - { "itemKey": "rs:rats_tail", "frequency": "always", "amount": 1, + { + "itemKey": "rs:rats_tail", + "frequency": "always", + "amount": 1, "amountMax": 1, "questRequirement": { "questId": "rs:witchs_potion", diff --git a/data/config/npcs/goblins.json b/data/config/npcs/goblins.json index 97710c4bb..8f4ec36f4 100644 --- a/data/config/npcs/goblins.json +++ b/data/config/npcs/goblins.json @@ -23,13 +23,11 @@ "ranged": -15 }, "animations": { - "attack": [ 310, 309 ], + "attack": [310, 309], "defend": 312, "death": 313 }, - "drop_table": [ - { "itemKey": "rs:bones", "frequency": "always", "amount": 1 } - ] + "drop_table": [{ "itemKey": "rs:bones", "frequency": "always", "amount": 1 }] } }, diff --git a/data/config/npcs/guards.json b/data/config/npcs/guards.json index 957afa01a..84f7a9990 100644 --- a/data/config/npcs/guards.json +++ b/data/config/npcs/guards.json @@ -1,38 +1,38 @@ { - "rs:guard": { - "variations": [ - { - "suffix": 0, - "game_id": 9 - }, - { - "suffix": 1, - "game_id": 10 - }, - { - "suffix": 2, - "game_id": 32 - }, - { - "suffix": 3, - "game_id": 206 - }, - { - "suffix": 4, - "game_id": 344 - }, - { - "suffix": 5, - "game_id": 345 - }, - { - "suffix": 6, - "game_id": 346 - }, - { - "suffix": 7, - "game_id": 368 - } - ] - } + "rs:guard": { + "variations": [ + { + "suffix": 0, + "game_id": 9 + }, + { + "suffix": 1, + "game_id": 10 + }, + { + "suffix": 2, + "game_id": 32 + }, + { + "suffix": 3, + "game_id": 206 + }, + { + "suffix": 4, + "game_id": 344 + }, + { + "suffix": 5, + "game_id": 345 + }, + { + "suffix": 6, + "game_id": 346 + }, + { + "suffix": 7, + "game_id": 368 + } + ] + } } diff --git a/data/config/shops/alkharid/alkharid-gem-trader.json b/data/config/shops/alkharid/alkharid-gem-trader.json index f281d1e73..5aa9c4d2c 100644 --- a/data/config/shops/alkharid/alkharid-gem-trader.json +++ b/data/config/shops/alkharid/alkharid-gem-trader.json @@ -1,50 +1,50 @@ { - "rs:alkharid_gem_trader": { - "name": "Gem Trader", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.70, - "rate_modifier": 0.03, - "stock": [ - { - "itemKey": "rs:uncut_sapphire", - "amount": 1, - "restock": 25000 - }, - { - "itemKey": "rs:uncut_emerald", - "amount": 1, - "restock": 40000 - }, - { - "itemKey": "rs:uncut_ruby", - "amount": 0, - "restock": 2000 - }, - { - "itemKey": "rs:uncut_diamond", - "amount": 0, - "restock": 4000 - }, - { - "itemKey": "rs:sapphire", - "amount": 1, - "restock": 15000 - }, - { - "itemKey": "rs:emerald", - "amount": 1, - "restock": 35000 - }, - { - "itemKey": "rs:ruby", - "amount": 0, - "restock": 2000 - }, - { - "itemKey": "rs:diamond", - "amount": 0, - "restock": 4000 - } - ] - } + "rs:alkharid_gem_trader": { + "name": "Gem Trader", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.7, + "rate_modifier": 0.03, + "stock": [ + { + "itemKey": "rs:uncut_sapphire", + "amount": 1, + "restock": 25000 + }, + { + "itemKey": "rs:uncut_emerald", + "amount": 1, + "restock": 40000 + }, + { + "itemKey": "rs:uncut_ruby", + "amount": 0, + "restock": 2000 + }, + { + "itemKey": "rs:uncut_diamond", + "amount": 0, + "restock": 4000 + }, + { + "itemKey": "rs:sapphire", + "amount": 1, + "restock": 15000 + }, + { + "itemKey": "rs:emerald", + "amount": 1, + "restock": 35000 + }, + { + "itemKey": "rs:ruby", + "amount": 0, + "restock": 2000 + }, + { + "itemKey": "rs:diamond", + "amount": 0, + "restock": 4000 + } + ] + } } diff --git a/data/config/shops/alkharid/dommiks-crafting-store.json b/data/config/shops/alkharid/dommiks-crafting-store.json index aa8fb941f..40114f710 100644 --- a/data/config/shops/alkharid/dommiks-crafting-store.json +++ b/data/config/shops/alkharid/dommiks-crafting-store.json @@ -1,55 +1,55 @@ { - "rs:dommiks_crafting_store": { - "name": "Dommik's Crafting Store", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.65, - "rate_modifier": 0.02, - "stock": [ - { - "itemKey": "rs:chisel", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:ring_mould", - "amount": 4, - "restock": 100 - }, - { - "itemKey": "rs:necklace_mould", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:amulet_mould", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:needle", - "amount": 3, - "restock": 100 - }, - { - "itemKey": "rs:thread", - "amount": 100, - "restock": 5 - }, - { - "itemKey": "rs:holy_mould", - "amount": 3, - "restock": 100 - }, - { - "itemKey": "rs:sickle_mould", - "amount": 6, - "restock": 15 - }, - { - "itemKey": "rs:tiara_mould", - "amount": 10, - "restock": 10 - } - ] - } + "rs:dommiks_crafting_store": { + "name": "Dommik's Crafting Store", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.65, + "rate_modifier": 0.02, + "stock": [ + { + "itemKey": "rs:chisel", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:ring_mould", + "amount": 4, + "restock": 100 + }, + { + "itemKey": "rs:necklace_mould", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:amulet_mould", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:needle", + "amount": 3, + "restock": 100 + }, + { + "itemKey": "rs:thread", + "amount": 100, + "restock": 5 + }, + { + "itemKey": "rs:holy_mould", + "amount": 3, + "restock": 100 + }, + { + "itemKey": "rs:sickle_mould", + "amount": 6, + "restock": 15 + }, + { + "itemKey": "rs:tiara_mould", + "amount": 10, + "restock": 10 + } + ] + } } diff --git a/data/config/shops/alkharid/louies-armored-legs.json b/data/config/shops/alkharid/louies-armored-legs.json index c1b4170b2..e6a032c8b 100644 --- a/data/config/shops/alkharid/louies-armored-legs.json +++ b/data/config/shops/alkharid/louies-armored-legs.json @@ -1,40 +1,40 @@ { - "rs:louies_armored_legs": { - "name": "Louie's Armoured Legs Bazaar", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.65, - "rate_modifier": 0.01, - "stock": [ - { - "itemKey": "rs:bronze_platelegs", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:iron_platelegs", - "amount": 3, - "restock": 400 - }, - { - "itemKey": "rs:steel_platelegs", - "amount": 2, - "restock": 900 - }, - { - "itemKey": "rs:black_platelegs", - "amount": 1, - "restock": 1200 - }, - { - "itemKey": "rs:mithril_platelegs", - "amount": 1, - "restock": 2000 - }, - { - "itemKey": "rs:adamant_platelegs", - "amount": 1, - "restock": 13000 - } - ] - } + "rs:louies_armored_legs": { + "name": "Louie's Armoured Legs Bazaar", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.65, + "rate_modifier": 0.01, + "stock": [ + { + "itemKey": "rs:bronze_platelegs", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:iron_platelegs", + "amount": 3, + "restock": 400 + }, + { + "itemKey": "rs:steel_platelegs", + "amount": 2, + "restock": 900 + }, + { + "itemKey": "rs:black_platelegs", + "amount": 1, + "restock": 1200 + }, + { + "itemKey": "rs:mithril_platelegs", + "amount": 1, + "restock": 2000 + }, + { + "itemKey": "rs:adamant_platelegs", + "amount": 1, + "restock": 13000 + } + ] + } } diff --git a/data/config/shops/alkharid/ranaels-skirt-store.json b/data/config/shops/alkharid/ranaels-skirt-store.json index 4c9de6e75..b065d433f 100644 --- a/data/config/shops/alkharid/ranaels-skirt-store.json +++ b/data/config/shops/alkharid/ranaels-skirt-store.json @@ -1,40 +1,40 @@ { - "rs:ranaels_skirt_store": { - "name": "Ranael's Super Skirt Store", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.65, - "rate_modifier": 0.01, - "stock": [ - { - "itemKey": "rs:bronze_plateskirt", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:iron_plateskirt", - "amount": 3, - "restock": 400 - }, - { - "itemKey": "rs:steel_plateskirt", - "amount": 2, - "restock": 900 - }, - { - "itemKey": "rs:black_plateskirt", - "amount": 1, - "restock": 1200 - }, - { - "itemKey": "rs:mithril_plateskirt", - "amount": 1, - "restock": 2000 - }, - { - "itemKey": "rs:adamant_plateskirt", - "amount": 1, - "restock": 13000 - } - ] - } + "rs:ranaels_skirt_store": { + "name": "Ranael's Super Skirt Store", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.65, + "rate_modifier": 0.01, + "stock": [ + { + "itemKey": "rs:bronze_plateskirt", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:iron_plateskirt", + "amount": 3, + "restock": 400 + }, + { + "itemKey": "rs:steel_plateskirt", + "amount": 2, + "restock": 900 + }, + { + "itemKey": "rs:black_plateskirt", + "amount": 1, + "restock": 1200 + }, + { + "itemKey": "rs:mithril_plateskirt", + "amount": 1, + "restock": 2000 + }, + { + "itemKey": "rs:adamant_plateskirt", + "amount": 1, + "restock": 13000 + } + ] + } } diff --git a/data/config/shops/lumbridge/bobs-axes.json b/data/config/shops/lumbridge/bobs-axes.json index c21b174fe..31bb9d887 100644 --- a/data/config/shops/lumbridge/bobs-axes.json +++ b/data/config/shops/lumbridge/bobs-axes.json @@ -1,45 +1,45 @@ { - "rs:lumbridge_bobs_axes": { - "name": "Bob's Brilliant Axes.", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.60, - "rate_modifier": 0.02, - "stock": [ - { - "itemKey": "rs:bronze_pickaxe", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:bronze_axe", - "amount": 10, - "restock": 100 - }, - { - "itemKey": "rs:iron_axe", - "amount": 5, - "restock": 200 - }, - { - "itemKey": "rs:steel_axe", - "amount": 3, - "restock": 400 - }, - { - "itemKey": "rs:iron_battleaxe", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:steel_battleaxe", - "amount": 2, - "restock": 200 - }, - { - "itemKey": "rs:mithril_battleaxe", - "amount": 1, - "restock": 3000 - } - ] - } + "rs:lumbridge_bobs_axes": { + "name": "Bob's Brilliant Axes.", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.6, + "rate_modifier": 0.02, + "stock": [ + { + "itemKey": "rs:bronze_pickaxe", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:bronze_axe", + "amount": 10, + "restock": 100 + }, + { + "itemKey": "rs:iron_axe", + "amount": 5, + "restock": 200 + }, + { + "itemKey": "rs:steel_axe", + "amount": 3, + "restock": 400 + }, + { + "itemKey": "rs:iron_battleaxe", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:steel_battleaxe", + "amount": 2, + "restock": 200 + }, + { + "itemKey": "rs:mithril_battleaxe", + "amount": 1, + "restock": 3000 + } + ] + } } diff --git a/data/config/shops/lumbridge/lumbridge-general-store.json b/data/config/shops/lumbridge/lumbridge-general-store.json index b809dcbd8..2bbce18f9 100644 --- a/data/config/shops/lumbridge/lumbridge-general-store.json +++ b/data/config/shops/lumbridge/lumbridge-general-store.json @@ -1,66 +1,66 @@ { - "rs:lumbridge_general_store": { - "name": "Lumbridge General Store", - "general_store": true, - "shop_sell_rate": 1.3, - "shop_buy_rate": 0.4, - "rate_modifier": 0.03, - "stock": [ - { - "itemKey": "rs:pot", - "amount": 5, - "restock": 10 - }, - { - "itemKey": "rs:jug", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:shears", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:knife", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:bucket", - "amount": 3, - "restock": 10 - }, - { - "itemKey": "rs:bowl", - "amount": 2, - "restock": 50 - }, - { - "itemKey": "rs:cake_tin", - "amount": 2, - "restock": 50 - }, - { - "itemKey": "rs:tinderbox", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:chisel", - "amount": 2, - "restock": 100 - }, - { - "itemKey": "rs:spade", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:hammer", - "amount": 5, - "restock": 100 - } - ] - } + "rs:lumbridge_general_store": { + "name": "Lumbridge General Store", + "general_store": true, + "shop_sell_rate": 1.3, + "shop_buy_rate": 0.4, + "rate_modifier": 0.03, + "stock": [ + { + "itemKey": "rs:pot", + "amount": 5, + "restock": 10 + }, + { + "itemKey": "rs:jug", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:shears", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:knife", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:bucket", + "amount": 3, + "restock": 10 + }, + { + "itemKey": "rs:bowl", + "amount": 2, + "restock": 50 + }, + { + "itemKey": "rs:cake_tin", + "amount": 2, + "restock": 50 + }, + { + "itemKey": "rs:tinderbox", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:chisel", + "amount": 2, + "restock": 100 + }, + { + "itemKey": "rs:spade", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:hammer", + "amount": 5, + "restock": 100 + } + ] + } } diff --git a/data/config/shops/portsarim/bettys-magic-emporium.json b/data/config/shops/portsarim/bettys-magic-emporium.json index f23b77241..6645b4d4b 100644 --- a/data/config/shops/portsarim/bettys-magic-emporium.json +++ b/data/config/shops/portsarim/bettys-magic-emporium.json @@ -1,65 +1,65 @@ { - "rs:bettys_magic_emporium": { - "name": "Betty's Magic Emporium", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.60, - "rate_modifier": 0.001, - "stock": [ - { - "itemKey": "rs:fire_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:water_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:air_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:earth_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:mind_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:body_rune", - "amount": 5000, - "restock": 10 - }, - { - "itemKey": "rs:chaos_rune", - "amount": 250, - "restock": 10 - }, - { - "itemKey": "rs:death_rune", - "amount": 250, - "restock": 15 - }, - { - "itemKey": "rs:eye_of_newt", - "amount": 300, - "restock": 10 - }, - { - "itemKey": "rs:wizard_hat_(black)", - "amount": 1, - "restock": 100 - }, - { - "itemKey": "rs:wizard_hat_(blue)", - "amount": 1, - "restock": 100 - } - ] - } + "rs:bettys_magic_emporium": { + "name": "Betty's Magic Emporium", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.6, + "rate_modifier": 0.001, + "stock": [ + { + "itemKey": "rs:fire_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:water_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:air_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:earth_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:mind_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:body_rune", + "amount": 5000, + "restock": 10 + }, + { + "itemKey": "rs:chaos_rune", + "amount": 250, + "restock": 10 + }, + { + "itemKey": "rs:death_rune", + "amount": 250, + "restock": 15 + }, + { + "itemKey": "rs:eye_of_newt", + "amount": 300, + "restock": 10 + }, + { + "itemKey": "rs:wizard_hat_(black)", + "amount": 1, + "restock": 100 + }, + { + "itemKey": "rs:wizard_hat_(blue)", + "amount": 1, + "restock": 100 + } + ] + } } diff --git a/data/config/shops/shilo-village/oblis-general-store.json b/data/config/shops/shilo-village/oblis-general-store.json index d10ea879c..f0fb107b2 100644 --- a/data/config/shops/shilo-village/oblis-general-store.json +++ b/data/config/shops/shilo-village/oblis-general-store.json @@ -1,126 +1,126 @@ { - "rs:oblis-general-store": { - "name": "Obli's General Store", - "general_store": true, - "shop_sell_rate": 1.5, - "rate_modifier": 0.02, - "shop_buy_rate": 0.5, - "stock": [ - { - "itemKey": "rs:tinderbox", - "amount": 2, - "restock": 500 - }, - { - "itemKey": "rs:vial", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:pestle_and_mortar", - "amount": 3, - "restock": 500 - }, - { - "itemKey": "rs:pot", - "amount": 3, - "restock": 500 - }, - { - "itemKey": "rs:bronze_axe", - "amount": 3, - "restock": 500 - }, - { - "itemKey": "rs:bronze_pickaxe", - "amount": 2, - "restock": 500 - }, - { - "itemKey": "rs:iron_axe", - "amount": 5, - "restock": 700 - }, - { - "itemKey": "rs:leather_body", - "amount": 12, - "restock": 500 - }, - { - "itemKey": "rs:leather_gloves", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:leather_boots", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:cooked_meat", - "amount": 2, - "restock": 500 - }, - { - "itemKey": "rs:bread", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:bronze_bar", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:spade", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:candle", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:unlit_torch", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:chisel", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:hammer", - "amount": 10, - "restock": 500 - }, - { - "itemKey": "rs:papyrus", - "amount": 50, - "restock": 200 - }, - { - "itemKey": "rs:charcoal", - "amount": 50, - "restock": 200 - }, - { - "itemKey": "rs:vial:water", - "amount": 50, - "restock": 200 - }, - { - "itemKey": "rs:machete", - "amount": 50, - "restock": 200 - }, - { - "itemKey": "rs:rope", - "amount": 10, - "restock": 200 - } - ] - } + "rs:oblis-general-store": { + "name": "Obli's General Store", + "general_store": true, + "shop_sell_rate": 1.5, + "rate_modifier": 0.02, + "shop_buy_rate": 0.5, + "stock": [ + { + "itemKey": "rs:tinderbox", + "amount": 2, + "restock": 500 + }, + { + "itemKey": "rs:vial", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:pestle_and_mortar", + "amount": 3, + "restock": 500 + }, + { + "itemKey": "rs:pot", + "amount": 3, + "restock": 500 + }, + { + "itemKey": "rs:bronze_axe", + "amount": 3, + "restock": 500 + }, + { + "itemKey": "rs:bronze_pickaxe", + "amount": 2, + "restock": 500 + }, + { + "itemKey": "rs:iron_axe", + "amount": 5, + "restock": 700 + }, + { + "itemKey": "rs:leather_body", + "amount": 12, + "restock": 500 + }, + { + "itemKey": "rs:leather_gloves", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:leather_boots", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:cooked_meat", + "amount": 2, + "restock": 500 + }, + { + "itemKey": "rs:bread", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:bronze_bar", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:spade", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:candle", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:unlit_torch", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:chisel", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:hammer", + "amount": 10, + "restock": 500 + }, + { + "itemKey": "rs:papyrus", + "amount": 50, + "restock": 200 + }, + { + "itemKey": "rs:charcoal", + "amount": 50, + "restock": 200 + }, + { + "itemKey": "rs:vial:water", + "amount": 50, + "restock": 200 + }, + { + "itemKey": "rs:machete", + "amount": 50, + "restock": 200 + }, + { + "itemKey": "rs:rope", + "amount": 10, + "restock": 200 + } + ] + } } diff --git a/data/config/shops/varrock/zaffs-staffs.json b/data/config/shops/varrock/zaffs-staffs.json index 59a8bb80c..5ebd966ba 100644 --- a/data/config/shops/varrock/zaffs-staffs.json +++ b/data/config/shops/varrock/zaffs-staffs.json @@ -1,45 +1,45 @@ { - "rs:zaffs_superior_staffs": { - "name": "Zaff's Superior Staffs", - "shop_sell_rate": 1.0, - "shop_buy_rate": 0.55, - "rate_modifier": 0.02, - "stock": [ - { - "itemKey": "rs:battlestaff", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:staff", - "amount": 5, - "restock": 100 - }, - { - "itemKey": "rs:magic_staff", - "amount": 5, - "restock": 200 - }, - { - "itemKey": "rs:staff_of_air", - "amount": 2, - "restock": 1000 - }, - { - "itemKey": "rs:staff_of_water", - "amount": 2, - "restock": 1000 - }, - { - "itemKey": "rs:staff_of_earth", - "amount": 2, - "restock": 1000 - }, - { - "itemKey": "rs:staff_of_fire", - "amount": 2, - "restock": 1000 - } - ] - } + "rs:zaffs_superior_staffs": { + "name": "Zaff's Superior Staffs", + "shop_sell_rate": 1.0, + "shop_buy_rate": 0.55, + "rate_modifier": 0.02, + "stock": [ + { + "itemKey": "rs:battlestaff", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:staff", + "amount": 5, + "restock": 100 + }, + { + "itemKey": "rs:magic_staff", + "amount": 5, + "restock": 200 + }, + { + "itemKey": "rs:staff_of_air", + "amount": 2, + "restock": 1000 + }, + { + "itemKey": "rs:staff_of_water", + "amount": 2, + "restock": 1000 + }, + { + "itemKey": "rs:staff_of_earth", + "amount": 2, + "restock": 1000 + }, + { + "itemKey": "rs:staff_of_fire", + "amount": 2, + "restock": 1000 + } + ] + } } diff --git a/data/config/widgets.json b/data/config/widgets.json index 440b218e3..c5ddd8a1c 100644 --- a/data/config/widgets.json +++ b/data/config/widgets.json @@ -1,118 +1,118 @@ { - "characterDesign": 269, - "furnace": { - "widgetId": 311, - "slots": { - "slot0": { - "modelId": 4, - "titleId": 16 - }, - "slot1": { - "modelId": 5, - "titleId": 20 - }, - "slot2": { - "modelId": 6, - "titleId": 24 - }, - "slot3": { - "modelId": 7, - "titleId": 28 - }, - "slot4": { - "modelId": 8, - "titleId": 32 - }, - "slot5": { - "modelId": 9, - "titleId": 36 - }, - "slot6": { - "modelId": 10, - "titleId": 40 - }, - "slot7": { - "modelId": 11, - "titleId": 44 - }, - "slot8": { - "modelId": 12, - "titleId": 48 - } - } - }, - "anvil": { - "widgetId": 312 - }, - "inventory": { - "widgetId": 149, - "containerId": 0 - }, - "disabledTabs": 151, - "equipment": { - "widgetId": 387, - "containerId": 25 - }, - "equipmentStats": { - "widgetId": 465, - "containerId": 103 - }, - "equipmentStatsInventory": { - "widgetId": 336, - "containerId": 0 - }, - "bank": { - "depositBoxWidget": { - "widgetId": 11, - "containerId": 61, - "titleText": 60 + "characterDesign": 269, + "furnace": { + "widgetId": 311, + "slots": { + "slot0": { + "modelId": 4, + "titleId": 16 + }, + "slot1": { + "modelId": 5, + "titleId": 20 + }, + "slot2": { + "modelId": 6, + "titleId": 24 + }, + "slot3": { + "modelId": 7, + "titleId": 28 + }, + "slot4": { + "modelId": 8, + "titleId": 32 + }, + "slot5": { + "modelId": 9, + "titleId": 36 + }, + "slot6": { + "modelId": 10, + "titleId": 40 + }, + "slot7": { + "modelId": 11, + "titleId": 44 + }, + "slot8": { + "modelId": 12, + "titleId": 48 + } + } }, - "pinSettingsWidget": { - "widgetId": 14 + "anvil": { + "widgetId": 312 }, - "screenWidget": { - "widgetId": 12, - "containerId": 89 + "inventory": { + "widgetId": 149, + "containerId": 0 }, - "tabWidget": { - "widgetId": 266, - "containerId": 0 - } - }, - "defaultCombatStyle": 92, - "skillGuide": 308, - "skillsTab": 320, - "friendsList": 131, - "ignoreList": 148, - "logoutTab": 182, - "settingsTab": 261, - "emotesTab": 464, - "musicPlayerTab": 239, - "prayerTab": 271, - "standardSpellbookTab": 192, - "questTab": 274, - "shop": { - "widgetId": 300, - "containerId": 75, - "title": 76 - }, - "shopPlayerInventory": { - "widgetId": 301, - "containerId": 0 - }, - "questJournal": 275, - "questReward": 277, - "welcomeScreen": 378, - "welcomeScreenChildren": { - "cogs": 16, - "question": 17, - "drama": 18, - "bankPin": 19, - "bankPinQuestion": 20, - "scamming": 21, - "bankPinKey": 22, - "christmas": 23, - "killcount": 24 - }, - "whatWouldYouLikeToSpin": 459 + "disabledTabs": 151, + "equipment": { + "widgetId": 387, + "containerId": 25 + }, + "equipmentStats": { + "widgetId": 465, + "containerId": 103 + }, + "equipmentStatsInventory": { + "widgetId": 336, + "containerId": 0 + }, + "bank": { + "depositBoxWidget": { + "widgetId": 11, + "containerId": 61, + "titleText": 60 + }, + "pinSettingsWidget": { + "widgetId": 14 + }, + "screenWidget": { + "widgetId": 12, + "containerId": 89 + }, + "tabWidget": { + "widgetId": 266, + "containerId": 0 + } + }, + "defaultCombatStyle": 92, + "skillGuide": 308, + "skillsTab": 320, + "friendsList": 131, + "ignoreList": 148, + "logoutTab": 182, + "settingsTab": 261, + "emotesTab": 464, + "musicPlayerTab": 239, + "prayerTab": 271, + "standardSpellbookTab": 192, + "questTab": 274, + "shop": { + "widgetId": 300, + "containerId": 75, + "title": 76 + }, + "shopPlayerInventory": { + "widgetId": 301, + "containerId": 0 + }, + "questJournal": 275, + "questReward": 277, + "welcomeScreen": 378, + "welcomeScreenChildren": { + "cogs": 16, + "question": 17, + "drama": 18, + "bankPin": 19, + "bankPinQuestion": 20, + "scamming": 21, + "bankPinKey": 22, + "christmas": 23, + "killcount": 24 + }, + "whatWouldYouLikeToSpin": 459 } diff --git a/data/config/xteas/435.json b/data/config/xteas/435.json index fe3048bf8..59a8e4be6 100644 --- a/data/config/xteas/435.json +++ b/data/config/xteas/435.json @@ -5,12 +5,7 @@ "name_hash": -1153472937, "name": "l40_55", "mapsquare": 10295, - "key": [ - -1920480496, - -1423914110, - 951774544, - -1419269290 - ] + "key": [-1920480496, -1423914110, 951774544, -1419269290] }, { "archive": 5, @@ -18,12 +13,7 @@ "name_hash": -1155051772, "name": "l29_80", "mapsquare": 7504, - "key": [ - 1847230655, - 1366615901, - 817013928, - -639754200 - ] + "key": [1847230655, 1366615901, 817013928, -639754200] }, { "archive": 5, @@ -31,12 +21,7 @@ "name_hash": -1418243906, "name": "l39_160", "mapsquare": 10144, - "key": [ - 265530509, - 2033515489, - -2022406749, - -591072091 - ] + "key": [265530509, 2033515489, -2022406749, -591072091] }, { "archive": 5, @@ -44,12 +29,7 @@ "name_hash": -1153472876, "name": "l40_74", "mapsquare": 10314, - "key": [ - -2020182865, - -861201399, - 1793241744, - -541294677 - ] + "key": [-2020182865, -861201399, 1793241744, -541294677] }, { "archive": 5, @@ -57,12 +37,7 @@ "name_hash": -1397926444, "name": "l40_160", "mapsquare": 10400, - "key": [ - -1656816922, - 1318311812, - -811481661, - 1625916625 - ] + "key": [-1656816922, 1318311812, -811481661, 1625916625] }, { "archive": 5, @@ -70,12 +45,7 @@ "name_hash": -1154366605, "name": "l31_75", "mapsquare": 8011, - "key": [ - -1287670691, - 690712165, - -1180498360, - -813635980 - ] + "key": [-1287670691, 690712165, -1180498360, -813635980] }, { "archive": 5, @@ -83,12 +53,7 @@ "name_hash": -1154366601, "name": "l31_79", "mapsquare": 8015, - "key": [ - -1320874262, - 1937053221, - 220952674, - 1903403210 - ] + "key": [-1320874262, 1937053221, 220952674, 1903403210] }, { "archive": 5, @@ -96,12 +61,7 @@ "name_hash": -1153472848, "name": "l40_81", "mapsquare": 10321, - "key": [ - -1416786366, - -183512307, - 774862574, - 1306347169 - ] + "key": [-1416786366, -183512307, 774862574, 1306347169] }, { "archive": 5, @@ -109,12 +69,7 @@ "name_hash": -1420090976, "name": "l37_153", "mapsquare": 9625, - "key": [ - -1160175957, - -906620860, - -585287228, - -1756474591 - ] + "key": [-1160175957, -906620860, -585287228, -1756474591] }, { "archive": 5, @@ -122,12 +77,7 @@ "name_hash": -1420090975, "name": "l37_154", "mapsquare": 9626, - "key": [ - -1086856428, - 1097853921, - -94537716, - -1037836120 - ] + "key": [-1086856428, 1097853921, -94537716, -1037836120] }, { "archive": 5, @@ -135,12 +85,7 @@ "name_hash": -1152519655, "name": "l51_46", "mapsquare": 13102, - "key": [ - -585304244, - -85656032, - -1672180123, - -889752362 - ] + "key": [-585304244, -85656032, -1672180123, -889752362] }, { "archive": 5, @@ -148,12 +93,7 @@ "name_hash": -1152519654, "name": "l51_47", "mapsquare": 13103, - "key": [ - 664202950, - 9942731, - 526981448, - 1961317213 - ] + "key": [664202950, 9942731, 526981448, 1961317213] }, { "archive": 5, @@ -161,12 +101,7 @@ "name_hash": -1152519624, "name": "l51_56", "mapsquare": 13112, - "key": [ - -294331294, - -882184793, - 66656303, - -1818669310 - ] + "key": [-294331294, -882184793, 66656303, -1818669310] }, { "archive": 5, @@ -174,12 +109,7 @@ "name_hash": -1152519622, "name": "l51_58", "mapsquare": 13114, - "key": [ - -1266416096, - 120695750, - -1880861340, - 2120698563 - ] + "key": [-1266416096, 120695750, -1880861340, 2120698563] }, { "archive": 5, @@ -187,12 +117,7 @@ "name_hash": -1153264429, "name": "l47_47", "mapsquare": 12079, - "key": [ - 339960494, - -1350930341, - -272469140, - 318766784 - ] + "key": [339960494, -1350930341, -272469140, 318766784] }, { "archive": 5, @@ -200,12 +125,7 @@ "name_hash": -1152519621, "name": "l51_59", "mapsquare": 13115, - "key": [ - 1818342784, - -642975152, - -355404480, - 132805372 - ] + "key": [1818342784, -642975152, -355404480, 132805372] }, { "archive": 5, @@ -213,12 +133,7 @@ "name_hash": -1153264428, "name": "l47_48", "mapsquare": 12080, - "key": [ - -1938428459, - -1838574783, - 131585942, - -1297008627 - ] + "key": [-1938428459, -1838574783, 131585942, -1297008627] }, { "archive": 5, @@ -226,12 +141,7 @@ "name_hash": -1153264427, "name": "l47_49", "mapsquare": 12081, - "key": [ - 613255413, - -1717776939, - -179584559, - -1310165510 - ] + "key": [613255413, -1717776939, -179584559, -1310165510] }, { "archive": 5, @@ -239,12 +149,7 @@ "name_hash": -1152519599, "name": "l51_60", "mapsquare": 13116, - "key": [ - 1370550295, - -820804475, - 1895373272, - 1832997410 - ] + "key": [1370550295, -820804475, 1895373272, 1832997410] }, { "archive": 5, @@ -252,12 +157,7 @@ "name_hash": -1152519598, "name": "l51_61", "mapsquare": 13117, - "key": [ - -1752848915, - -1242872593, - 1012298354, - -1076490243 - ] + "key": [-1752848915, -1242872593, 1012298354, -1076490243] }, { "archive": 5, @@ -265,12 +165,7 @@ "name_hash": -1153264402, "name": "l47_53", "mapsquare": 12085, - "key": [ - 866634875, - 2126690507, - 1264568376, - 2107515492 - ] + "key": [866634875, 2126690507, 1264568376, 2107515492] }, { "archive": 5, @@ -278,12 +173,7 @@ "name_hash": -1153264399, "name": "l47_56", "mapsquare": 12088, - "key": [ - 344960338, - -452527992, - 1340005990, - -1328736855 - ] + "key": [344960338, -452527992, 1340005990, -1328736855] }, { "archive": 5, @@ -291,12 +181,7 @@ "name_hash": -1153264398, "name": "l47_57", "mapsquare": 12089, - "key": [ - -551791250, - -2032976862, - -1354246732, - 1795367998 - ] + "key": [-551791250, -2032976862, -1354246732, 1795367998] }, { "archive": 5, @@ -304,12 +189,7 @@ "name_hash": -1153264397, "name": "l47_58", "mapsquare": 12090, - "key": [ - -2012109696, - -607715631, - -468949176, - 1368365998 - ] + "key": [-2012109696, -607715631, -468949176, 1368365998] }, { "archive": 5, @@ -317,12 +197,7 @@ "name_hash": -1153264396, "name": "l47_59", "mapsquare": 12091, - "key": [ - -2111919909, - -1125782501, - -1802382602, - 2137630247 - ] + "key": [-2111919909, -1125782501, -1802382602, 2137630247] }, { "archive": 5, @@ -330,12 +205,7 @@ "name_hash": -1153413382, "name": "l42_49", "mapsquare": 10801, - "key": [ - -1831859863, - -1836056891, - 342489401, - 1312886995 - ] + "key": [-1831859863, -1836056891, 342489401, 1312886995] }, { "archive": 5, @@ -343,12 +213,7 @@ "name_hash": -1153264374, "name": "l47_60", "mapsquare": 12092, - "key": [ - 111448945, - 1997179939, - -1992758838, - -904080104 - ] + "key": [111448945, 1997179939, -1992758838, -904080104] }, { "archive": 5, @@ -356,12 +221,7 @@ "name_hash": -1153264373, "name": "l47_61", "mapsquare": 12093, - "key": [ - -901249604, - 892308020, - 1075683735, - -148430952 - ] + "key": [-901249604, 892308020, 1075683735, -148430952] }, { "archive": 5, @@ -369,12 +229,7 @@ "name_hash": -1153413359, "name": "l42_51", "mapsquare": 10803, - "key": [ - 632564181, - 298843585, - -1472601465, - -1065203254 - ] + "key": [632564181, 298843585, -1472601465, -1065203254] }, { "archive": 5, @@ -382,12 +237,7 @@ "name_hash": -1153413358, "name": "l42_52", "mapsquare": 10804, - "key": [ - 844993707, - -1910359056, - -477807005, - 1502341650 - ] + "key": [844993707, -1910359056, -477807005, 1502341650] }, { "archive": 5, @@ -395,12 +245,7 @@ "name_hash": -1369297323, "name": "l50_151", "mapsquare": 12951, - "key": [ - -700278939, - 1204517853, - 912770506, - 985515932 - ] + "key": [-700278939, 1204517853, 912770506, 985515932] }, { "archive": 5, @@ -408,12 +253,7 @@ "name_hash": -1154158159, "name": "l38_47", "mapsquare": 9775, - "key": [ - 358467, - -1032890524, - -323905369, - 672132700 - ] + "key": [358467, -1032890524, -323905369, 672132700] }, { "archive": 5, @@ -421,12 +261,7 @@ "name_hash": -1154158133, "name": "l38_52", "mapsquare": 9780, - "key": [ - 23047955, - 374207630, - -14357742, - 487844353 - ] + "key": [23047955, 374207630, -14357742, 487844353] }, { "archive": 5, @@ -434,12 +269,7 @@ "name_hash": -1154158130, "name": "l38_55", "mapsquare": 9783, - "key": [ - -697645230, - -219261751, - 668010484, - -637416792 - ] + "key": [-697645230, -219261751, 668010484, -637416792] }, { "archive": 5, @@ -447,12 +277,7 @@ "name_hash": -1153413293, "name": "l42_75", "mapsquare": 10827, - "key": [ - -837303631, - -267210523, - -2043344605, - 99880496 - ] + "key": [-837303631, -267210523, -2043344605, 99880496] }, { "archive": 5, @@ -460,12 +285,7 @@ "name_hash": -1368373827, "name": "l51_147", "mapsquare": 13203, - "key": [ - -1342258113, - -2106603709, - 395365404, - -973258459 - ] + "key": [-1342258113, -2106603709, 395365404, -973258459] }, { "archive": 5, @@ -473,12 +293,7 @@ "name_hash": -1152370701, "name": "l56_45", "mapsquare": 14381, - "key": [ - -534048527, - 1614741928, - -469012711, - 1064350100 - ] + "key": [-534048527, 1614741928, -469012711, 1064350100] }, { "archive": 5, @@ -486,12 +301,7 @@ "name_hash": -1154158069, "name": "l38_74", "mapsquare": 9802, - "key": [ - -1207560898, - -2121890421, - -1280361853, - 1268736089 - ] + "key": [-1207560898, -2121890421, -1280361853, 1268736089] }, { "archive": 5, @@ -499,12 +309,7 @@ "name_hash": -1368373799, "name": "l51_154", "mapsquare": 13210, - "key": [ - -1504547443, - 1455578463, - -1808313124, - -45471826 - ] + "key": [-1504547443, 1455578463, -1808313124, -45471826] }, { "archive": 5, @@ -512,12 +317,7 @@ "name_hash": -1154307027, "name": "l33_71", "mapsquare": 8519, - "key": [ - -2051430502, - -746663069, - -593970049, - 379050420 - ] + "key": [-2051430502, -746663069, -593970049, 379050420] }, { "archive": 5, @@ -525,12 +325,7 @@ "name_hash": -1154307026, "name": "l33_72", "mapsquare": 8520, - "key": [ - 576327208, - 1659610549, - -1319545488, - -1984379615 - ] + "key": [576327208, 1659610549, -1319545488, -1984379615] }, { "archive": 5, @@ -538,12 +333,7 @@ "name_hash": -1154307025, "name": "l33_73", "mapsquare": 8521, - "key": [ - -1909603451, - -596972288, - -446203583, - -1017538492 - ] + "key": [-1909603451, -596972288, -446203583, -1017538492] }, { "archive": 5, @@ -551,12 +341,7 @@ "name_hash": -1393308893, "name": "l45_148", "mapsquare": 11668, - "key": [ - 1094922095, - -1747387328, - 1439302672, - 1510179242 - ] + "key": [1094922095, -1747387328, 1439302672, 1510179242] }, { "archive": 5, @@ -564,12 +349,7 @@ "name_hash": -1393308869, "name": "l45_151", "mapsquare": 11671, - "key": [ - 517807890, - -107570269, - 1542962182, - -1495382393 - ] + "key": [517807890, -107570269, 1542962182, -1495382393] }, { "archive": 5, @@ -577,12 +357,7 @@ "name_hash": -1393308868, "name": "l45_152", "mapsquare": 11672, - "key": [ - 59956468, - -1316944326, - -1514599528, - 979714228 - ] + "key": [59956468, -1316944326, -1514599528, 979714228] }, { "archive": 5, @@ -590,12 +365,7 @@ "name_hash": -1393308867, "name": "l45_153", "mapsquare": 11673, - "key": [ - 343838952, - -181461714, - 1044748667, - 1241583057 - ] + "key": [343838952, -181461714, 1044748667, 1241583057] }, { "archive": 5, @@ -603,12 +373,7 @@ "name_hash": -1155051798, "name": "l29_75", "mapsquare": 7499, - "key": [ - 389242534, - 1468756327, - 1739858109, - -397529213 - ] + "key": [389242534, 1468756327, 1739858109, -397529213] }, { "archive": 5, @@ -616,12 +381,7 @@ "name_hash": -1418243959, "name": "l39_149", "mapsquare": 10133, - "key": [ - -1295008659, - 266597781, - -348722649, - -387821353 - ] + "key": [-1295008659, 266597781, -348722649, -387821353] }, { "archive": 5, @@ -629,12 +389,7 @@ "name_hash": -1418243937, "name": "l39_150", "mapsquare": 10134, - "key": [ - -169090672, - -418150474, - -663319294, - 345797130 - ] + "key": [-169090672, -418150474, -663319294, 345797130] }, { "archive": 5, @@ -642,12 +397,7 @@ "name_hash": -1418243934, "name": "l39_153", "mapsquare": 10137, - "key": [ - 309023294, - 10701046, - 752820323, - 320724862 - ] + "key": [309023294, 10701046, 752820323, 320724862] }, { "archive": 5, @@ -655,12 +405,7 @@ "name_hash": -1418243933, "name": "l39_154", "mapsquare": 10138, - "key": [ - -1266932509, - 1159824249, - 1189711903, - 1903826998 - ] + "key": [-1266932509, 1159824249, 1189711903, 1903826998] }, { "archive": 5, @@ -668,12 +413,7 @@ "name_hash": -1152460047, "name": "l53_51", "mapsquare": 13619, - "key": [ - 712676739, - -1616631519, - -393806187, - 1432842778 - ] + "key": [712676739, -1616631519, -393806187, 1432842778] }, { "archive": 5, @@ -681,12 +421,7 @@ "name_hash": -1152460046, "name": "l53_52", "mapsquare": 13620, - "key": [ - -1340730148, - -1509744228, - -755242060, - 937448072 - ] + "key": [-1340730148, -1509744228, -755242060, 937448072] }, { "archive": 5, @@ -694,12 +429,7 @@ "name_hash": -1152460045, "name": "l53_53", "mapsquare": 13621, - "key": [ - -58207297, - 135788372, - -1606570127, - 662309804 - ] + "key": [-58207297, 135788372, -1606570127, 662309804] }, { "archive": 5, @@ -707,12 +437,7 @@ "name_hash": -1153204846, "name": "l49_48", "mapsquare": 12592, - "key": [ - -794001650, - -436110669, - 1193837402, - 1311524977 - ] + "key": [-794001650, -436110669, 1193837402, 1311524977] }, { "archive": 5, @@ -720,12 +445,7 @@ "name_hash": -1153204845, "name": "l49_49", "mapsquare": 12593, - "key": [ - -544590439, - -1841162484, - -767714061, - 1725894803 - ] + "key": [-544590439, -1841162484, -767714061, 1725894803] }, { "archive": 5, @@ -733,12 +453,7 @@ "name_hash": -1153204823, "name": "l49_50", "mapsquare": 12594, - "key": [ - -120447093, - 579654861, - -527409529, - 1730758809 - ] + "key": [-120447093, 579654861, -527409529, 1730758809] }, { "archive": 5, @@ -746,12 +461,7 @@ "name_hash": -1152370700, "name": "l56_46", "mapsquare": 14382, - "key": [ - -2047578817, - 357439085, - 332136595, - 1757066622 - ] + "key": [-2047578817, 357439085, 332136595, 1757066622] }, { "archive": 5, @@ -759,12 +469,7 @@ "name_hash": -1153204817, "name": "l49_56", "mapsquare": 12600, - "key": [ - 2086237847, - -2000241337, - 787272168, - -1342875227 - ] + "key": [2086237847, -2000241337, 787272168, -1342875227] }, { "archive": 5, @@ -772,12 +477,7 @@ "name_hash": -1153204816, "name": "l49_57", "mapsquare": 12601, - "key": [ - -360556539, - 1198026803, - -609365963, - -1563087824 - ] + "key": [-360556539, 1198026803, -609365963, -1563087824] }, { "archive": 5, @@ -785,12 +485,7 @@ "name_hash": -1153204815, "name": "l49_58", "mapsquare": 12602, - "key": [ - -1597607397, - -2146719506, - -1185304014, - 1704592002 - ] + "key": [-1597607397, -2146719506, -1185304014, 1704592002] }, { "archive": 5, @@ -798,12 +493,7 @@ "name_hash": -1153353802, "name": "l44_47", "mapsquare": 11311, - "key": [ - 255517588, - -1240190218, - -693538893, - 52321524 - ] + "key": [255517588, -1240190218, -693538893, 52321524] }, { "archive": 5, @@ -811,12 +501,7 @@ "name_hash": -1153204814, "name": "l49_59", "mapsquare": 12603, - "key": [ - 1903637882, - -2078269745, - 1154595732, - 2025457352 - ] + "key": [1903637882, -2078269745, 1154595732, 2025457352] }, { "archive": 5, @@ -824,12 +509,7 @@ "name_hash": -1153204792, "name": "l49_60", "mapsquare": 12604, - "key": [ - -1812120898, - -1662909112, - -1432124543, - 571589094 - ] + "key": [-1812120898, -1662909112, -1432124543, 571589094] }, { "archive": 5, @@ -837,12 +517,7 @@ "name_hash": -1153204791, "name": "l49_61", "mapsquare": 12605, - "key": [ - 794830896, - -1814271030, - 54960303, - 1749986908 - ] + "key": [794830896, -1814271030, 54960303, 1749986908] }, { "archive": 5, @@ -850,12 +525,7 @@ "name_hash": -1153353775, "name": "l44_53", "mapsquare": 11317, - "key": [ - 1589220603, - 1966511687, - -1108893479, - -635825550 - ] + "key": [1589220603, 1966511687, -1108893479, -635825550] }, { "archive": 5, @@ -863,12 +533,7 @@ "name_hash": -1391461850, "name": "l47_149", "mapsquare": 12181, - "key": [ - -1585897411, - -486973222, - 976725192, - 587846488 - ] + "key": [-1585897411, -486973222, 976725192, 587846488] }, { "archive": 5, @@ -876,12 +541,7 @@ "name_hash": -1397926499, "name": "l40_147", "mapsquare": 10387, - "key": [ - 1215785755, - 210499977, - -2093512319, - -625901574 - ] + "key": [1215785755, 210499977, -2093512319, -625901574] }, { "archive": 5, @@ -889,12 +549,7 @@ "name_hash": -1152340910, "name": "l57_45", "mapsquare": 14637, - "key": [ - 1954698915, - 587858534, - -1998840957, - -860751267 - ] + "key": [1954698915, 587858534, -1998840957, -860751267] }, { "archive": 5, @@ -902,12 +557,7 @@ "name_hash": -1397926498, "name": "l40_148", "mapsquare": 10388, - "key": [ - 1415243362, - 801135032, - -385381783, - -83383530 - ] + "key": [1415243362, 801135032, -385381783, -83383530] }, { "archive": 5, @@ -915,12 +565,7 @@ "name_hash": -1153353711, "name": "l44_75", "mapsquare": 11339, - "key": [ - -1717666269, - 1594420520, - -1751131464, - -154240780 - ] + "key": [-1717666269, 1594420520, -1751131464, -154240780] }, { "archive": 5, @@ -928,12 +573,7 @@ "name_hash": -1397926471, "name": "l40_154", "mapsquare": 10394, - "key": [ - -2102331685, - 781435808, - 1774321038, - -660278831 - ] + "key": [-2102331685, 781435808, 1774321038, -660278831] }, { "archive": 5, @@ -941,12 +581,7 @@ "name_hash": -1154396396, "name": "l30_75", "mapsquare": 7755, - "key": [ - 1467763642, - -2057666779, - 1692811, - 1234049587 - ] + "key": [1467763642, -2057666779, 1692811, 1234049587] }, { "archive": 5, @@ -954,12 +589,7 @@ "name_hash": -1152340907, "name": "l57_48", "mapsquare": 14640, - "key": [ - -95254230, - -1094148730, - -1768319507, - 105210786 - ] + "key": [-95254230, -1094148730, -1768319507, 105210786] }, { "archive": 5, @@ -967,12 +597,7 @@ "name_hash": -1389614782, "name": "l49_154", "mapsquare": 12698, - "key": [ - 1313997139, - 413705980, - -1786270630, - -1211819932 - ] + "key": [1313997139, 413705980, -1786270630, -1211819932] }, { "archive": 5, @@ -980,12 +605,7 @@ "name_hash": -1152311119, "name": "l58_45", "mapsquare": 14893, - "key": [ - -102394113, - 1484262111, - 933695487, - -283213546 - ] + "key": [-102394113, 1484262111, 933695487, -283213546] }, { "archive": 5, @@ -993,12 +613,7 @@ "name_hash": -1396079432, "name": "l42_151", "mapsquare": 10903, - "key": [ - -1260800958, - -1306263170, - 319256612, - 1478365211 - ] + "key": [-1260800958, -1306263170, 319256612, 1478365211] }, { "archive": 5, @@ -1006,12 +621,7 @@ "name_hash": -1152549446, "name": "l50_46", "mapsquare": 12846, - "key": [ - -1128107273, - -1379368189, - -1166299202, - 1367493265 - ] + "key": [-1128107273, -1379368189, -1166299202, 1367493265] }, { "archive": 5, @@ -1019,12 +629,7 @@ "name_hash": -1396079431, "name": "l42_152", "mapsquare": 10904, - "key": [ - 299433082, - 1093303265, - 1627642083, - 1856381978 - ] + "key": [299433082, 1093303265, 1627642083, 1856381978] }, { "archive": 5, @@ -1032,12 +637,7 @@ "name_hash": -1396079430, "name": "l42_153", "mapsquare": 10905, - "key": [ - 15962844, - -263608354, - -1698286677, - -1506930528 - ] + "key": [15962844, -263608354, -1698286677, -1506930528] }, { "archive": 5, @@ -1045,12 +645,7 @@ "name_hash": -1152549444, "name": "l50_48", "mapsquare": 12848, - "key": [ - -472467501, - 942301843, - -1235756555, - 1092807961 - ] + "key": [-472467501, 942301843, -1235756555, 1092807961] }, { "archive": 5, @@ -1058,12 +653,7 @@ "name_hash": -1152549443, "name": "l50_49", "mapsquare": 12849, - "key": [ - 856523891, - -869724785, - 1850232409, - -674722748 - ] + "key": [856523891, -869724785, 1850232409, -674722748] }, { "archive": 5, @@ -1071,12 +661,7 @@ "name_hash": -1152549415, "name": "l50_56", "mapsquare": 12856, - "key": [ - 1065837316, - 566874993, - -395031456, - -1005765069 - ] + "key": [1065837316, 566874993, -395031456, -1005765069] }, { "archive": 5, @@ -1084,12 +669,7 @@ "name_hash": -1153294222, "name": "l46_45", "mapsquare": 11821, - "key": [ - -1676526445, - -459611821, - 895613340, - -1034819584 - ] + "key": [-1676526445, -459611821, 895613340, -1034819584] }, { "archive": 5, @@ -1097,12 +677,7 @@ "name_hash": -1152549414, "name": "l50_57", "mapsquare": 12857, - "key": [ - 1315061238, - 798718066, - -593804887, - 1674278988 - ] + "key": [1315061238, 798718066, -593804887, 1674278988] }, { "archive": 5, @@ -1110,12 +685,7 @@ "name_hash": -1153294221, "name": "l46_46", "mapsquare": 11822, - "key": [ - 1634541811, - 1149149862, - -1352773374, - 843504994 - ] + "key": [1634541811, 1149149862, -1352773374, 843504994] }, { "archive": 5, @@ -1123,12 +693,7 @@ "name_hash": -1152549413, "name": "l50_58", "mapsquare": 12858, - "key": [ - 1739165090, - 1380036717, - 1760229212, - -243206298 - ] + "key": [1739165090, 1380036717, 1760229212, -243206298] }, { "archive": 5, @@ -1136,12 +701,7 @@ "name_hash": -1153294220, "name": "l46_47", "mapsquare": 11823, - "key": [ - -256018875, - 2059756735, - 1142698660, - 1129906231 - ] + "key": [-256018875, 2059756735, 1142698660, 1129906231] }, { "archive": 5, @@ -1149,12 +709,7 @@ "name_hash": -1152311117, "name": "l58_47", "mapsquare": 14895, - "key": [ - 1294223700, - 778677766, - -2141486577, - 1402077049 - ] + "key": [1294223700, 778677766, -2141486577, 1402077049] }, { "archive": 5, @@ -1162,12 +717,7 @@ "name_hash": -1152549412, "name": "l50_59", "mapsquare": 12859, - "key": [ - 426800430, - 789609597, - 2049374976, - 800682309 - ] + "key": [426800430, 789609597, 2049374976, 800682309] }, { "archive": 5, @@ -1175,12 +725,7 @@ "name_hash": -1153294219, "name": "l46_48", "mapsquare": 11824, - "key": [ - -1116727390, - -659788658, - 307002260, - 354360287 - ] + "key": [-1116727390, -659788658, 307002260, 354360287] }, { "archive": 5, @@ -1188,12 +733,7 @@ "name_hash": -1153294218, "name": "l46_49", "mapsquare": 11825, - "key": [ - 1525999114, - 1162595366, - 465333685, - 1306030426 - ] + "key": [1525999114, 1162595366, 465333685, 1306030426] }, { "archive": 5, @@ -1201,12 +741,7 @@ "name_hash": -1152549390, "name": "l50_60", "mapsquare": 12860, - "key": [ - 189035026, - -14034698, - -394067455, - -734636364 - ] + "key": [189035026, -14034698, -394067455, -734636364] }, { "archive": 5, @@ -1214,12 +749,7 @@ "name_hash": -1152549389, "name": "l50_61", "mapsquare": 12861, - "key": [ - 1816963481, - -496926322, - 1214068433, - 1190940799 - ] + "key": [1816963481, -496926322, 1214068433, 1190940799] }, { "archive": 5, @@ -1227,12 +757,7 @@ "name_hash": -1153294190, "name": "l46_56", "mapsquare": 11832, - "key": [ - 1106039923, - -761356647, - -2114299754, - 948992246 - ] + "key": [1106039923, -761356647, -2114299754, 948992246] }, { "archive": 5, @@ -1240,12 +765,7 @@ "name_hash": -1153294188, "name": "l46_58", "mapsquare": 11834, - "key": [ - 173215366, - -1499360859, - 472196248, - 1020719132 - ] + "key": [173215366, -1499360859, 472196248, 1020719132] }, { "archive": 5, @@ -1253,12 +773,7 @@ "name_hash": -1153294187, "name": "l46_59", "mapsquare": 11835, - "key": [ - 1629126437, - 1652550905, - 841609762, - -317888116 - ] + "key": [1629126437, 1652550905, 841609762, -317888116] }, { "archive": 5, @@ -1266,12 +781,7 @@ "name_hash": -1153443174, "name": "l41_48", "mapsquare": 10544, - "key": [ - -895303896, - 744949463, - -2033369513, - 338766696 - ] + "key": [-895303896, 744949463, -2033369513, 338766696] }, { "archive": 5, @@ -1279,12 +789,7 @@ "name_hash": -1153294165, "name": "l46_60", "mapsquare": 11836, - "key": [ - 1310410800, - 423198468, - -1302324807, - 259991487 - ] + "key": [1310410800, 423198468, -1302324807, 259991487] }, { "archive": 5, @@ -1292,12 +797,7 @@ "name_hash": -1153294164, "name": "l46_61", "mapsquare": 11837, - "key": [ - 1906296384, - 292432464, - 594794920, - -1546603049 - ] + "key": [1906296384, 292432464, 594794920, -1546603049] }, { "archive": 5, @@ -1305,12 +805,7 @@ "name_hash": -1153443148, "name": "l41_53", "mapsquare": 10549, - "key": [ - 1856240647, - -1307099618, - -1197945308, - -2122254516 - ] + "key": [1856240647, -1307099618, -1197945308, -2122254516] }, { "archive": 5, @@ -1318,12 +813,7 @@ "name_hash": -1153443147, "name": "l41_54", "mapsquare": 10550, - "key": [ - 957349475, - -496721990, - 1780878747, - -1948737082 - ] + "key": [957349475, -496721990, 1780878747, -1948737082] }, { "archive": 5, @@ -1331,12 +821,7 @@ "name_hash": -1153443146, "name": "l41_55", "mapsquare": 10551, - "key": [ - 1042296612, - -799710697, - -433924400, - -596565458 - ] + "key": [1042296612, -799710697, -433924400, -596565458] }, { "archive": 5, @@ -1344,12 +829,7 @@ "name_hash": -1153443145, "name": "l41_56", "mapsquare": 10552, - "key": [ - 1428473548, - -513790027, - 959922611, - 2094550429 - ] + "key": [1428473548, -513790027, 959922611, 2094550429] }, { "archive": 5, @@ -1357,12 +837,7 @@ "name_hash": -1154187948, "name": "l37_49", "mapsquare": 9521, - "key": [ - -1204382617, - 894320578, - -2017151095, - -679668405 - ] + "key": [-1204382617, 894320578, -2017151095, -679668405] }, { "archive": 5, @@ -1370,12 +845,7 @@ "name_hash": -1154187926, "name": "l37_50", "mapsquare": 9522, - "key": [ - 1252542168, - -1448059709, - 1122042436, - -1636001244 - ] + "key": [1252542168, -1448059709, 1122042436, -1636001244] }, { "archive": 5, @@ -1383,12 +853,7 @@ "name_hash": -1154187925, "name": "l37_51", "mapsquare": 9523, - "key": [ - -1310187207, - -834726064, - -1799766719, - 1699616161 - ] + "key": [-1310187207, -834726064, -1799766719, 1699616161] }, { "archive": 5, @@ -1396,12 +861,7 @@ "name_hash": -1154187922, "name": "l37_54", "mapsquare": 9526, - "key": [ - -2064252262, - -887239839, - 1167799401, - 858861043 - ] + "key": [-2064252262, -887239839, 1167799401, 858861043] }, { "archive": 5, @@ -1409,12 +869,7 @@ "name_hash": -1153443084, "name": "l41_75", "mapsquare": 10571, - "key": [ - 1446859333, - -1375675929, - -760014134, - 1113381222 - ] + "key": [1446859333, -1375675929, -760014134, 1113381222] }, { "archive": 5, @@ -1422,12 +877,7 @@ "name_hash": -1154187861, "name": "l37_73", "mapsquare": 9545, - "key": [ - 219605670, - 414657294, - -2055023109, - -49887033 - ] + "key": [219605670, 414657294, -2055023109, -49887033] }, { "archive": 5, @@ -1435,12 +885,7 @@ "name_hash": -1154187859, "name": "l37_75", "mapsquare": 9547, - "key": [ - -157587105, - -806602516, - 1521207142, - -727421759 - ] + "key": [-157587105, -806602516, 1521207142, -727421759] }, { "archive": 5, @@ -1448,12 +893,7 @@ "name_hash": -1152281328, "name": "l59_45", "mapsquare": 15149, - "key": [ - -1200628316, - 15132614, - -465260385, - -1525542932 - ] + "key": [-1200628316, 15132614, -465260385, -1525542932] }, { "archive": 5, @@ -1461,12 +901,7 @@ "name_hash": -1394232414, "name": "l44_148", "mapsquare": 11412, - "key": [ - -119590785, - -577007136, - 324812522, - 2041325243 - ] + "key": [-119590785, -577007136, 324812522, 2041325243] }, { "archive": 5, @@ -1474,12 +909,7 @@ "name_hash": -1394232389, "name": "l44_152", "mapsquare": 11416, - "key": [ - 698674506, - 1358331305, - 913172931, - 765272229 - ] + "key": [698674506, 1358331305, 913172931, 765272229] }, { "archive": 5, @@ -1487,12 +917,7 @@ "name_hash": -1394232388, "name": "l44_153", "mapsquare": 11417, - "key": [ - 397843162, - 248774218, - -228700444, - -531210715 - ] + "key": [397843162, 248774218, -228700444, -531210715] }, { "archive": 5, @@ -1500,12 +925,7 @@ "name_hash": -1394232386, "name": "l44_155", "mapsquare": 11419, - "key": [ - 1015780380, - -702872379, - -62881570, - -362521171 - ] + "key": [1015780380, -702872379, -62881570, -362521171] }, { "archive": 5, @@ -1513,12 +933,7 @@ "name_hash": -1419167482, "name": "l38_147", "mapsquare": 9875, - "key": [ - -266211268, - 1666415569, - -594364895, - -521555462 - ] + "key": [-266211268, 1666415569, -594364895, -521555462] }, { "archive": 5, @@ -1526,12 +941,7 @@ "name_hash": -1419167454, "name": "l38_154", "mapsquare": 9882, - "key": [ - 1405534886, - 1766737228, - -31518279, - -1845608276 - ] + "key": [1405534886, 1766737228, -31518279, -1845608276] }, { "archive": 5, @@ -1539,12 +949,7 @@ "name_hash": -1152489861, "name": "l52_49", "mapsquare": 13361, - "key": [ - 1703044360, - 924675594, - 1161742507, - -1174930763 - ] + "key": [1703044360, 924675594, 1161742507, -1174930763] }, { "archive": 5, @@ -1552,12 +957,7 @@ "name_hash": -1152489839, "name": "l52_50", "mapsquare": 13362, - "key": [ - 1001397515, - 373830398, - 1721578513, - -710173574 - ] + "key": [1001397515, 373830398, 1721578513, -710173574] }, { "archive": 5, @@ -1565,12 +965,7 @@ "name_hash": -1152489838, "name": "l52_51", "mapsquare": 13363, - "key": [ - -1632087500, - -620280348, - 22360696, - 1386365966 - ] + "key": [-1632087500, -620280348, 22360696, 1386365966] }, { "archive": 5, @@ -1578,12 +973,7 @@ "name_hash": -1152489833, "name": "l52_56", "mapsquare": 13368, - "key": [ - -922499048, - 1143654396, - 1593518953, - 1160947087 - ] + "key": [-922499048, 1143654396, 1593518953, 1160947087] }, { "archive": 5, @@ -1591,12 +981,7 @@ "name_hash": -1152489832, "name": "l52_57", "mapsquare": 13369, - "key": [ - -857763581, - -71502428, - -1316897039, - -786191624 - ] + "key": [-857763581, -71502428, -1316897039, -786191624] }, { "archive": 5, @@ -1604,12 +989,7 @@ "name_hash": -1152489831, "name": "l52_58", "mapsquare": 13370, - "key": [ - -1259912756, - -640452721, - 1196310747, - 269878509 - ] + "key": [-1259912756, -640452721, 1196310747, 269878509] }, { "archive": 5, @@ -1617,12 +997,7 @@ "name_hash": -1153234638, "name": "l48_47", "mapsquare": 12335, - "key": [ - -387260899, - -2132243418, - 654609855, - -1092457792 - ] + "key": [-387260899, -2132243418, 654609855, -1092457792] }, { "archive": 5, @@ -1630,12 +1005,7 @@ "name_hash": -1152489830, "name": "l52_59", "mapsquare": 13371, - "key": [ - -398274614, - 1285418048, - 876964091, - -1818498048 - ] + "key": [-398274614, 1285418048, 876964091, -1818498048] }, { "archive": 5, @@ -1643,12 +1013,7 @@ "name_hash": -1153234637, "name": "l48_48", "mapsquare": 12336, - "key": [ - 1152832719, - 1703327384, - -664371384, - 1662584632 - ] + "key": [1152832719, 1703327384, -664371384, 1662584632] }, { "archive": 5, @@ -1656,12 +1021,7 @@ "name_hash": -1152489808, "name": "l52_60", "mapsquare": 13372, - "key": [ - 865568678, - -2124731942, - 491055641, - 1024391843 - ] + "key": [865568678, -2124731942, 491055641, 1024391843] }, { "archive": 5, @@ -1669,12 +1029,7 @@ "name_hash": -1152489807, "name": "l52_61", "mapsquare": 13373, - "key": [ - -2063060546, - 1762500570, - 940695155, - -1216823417 - ] + "key": [-2063060546, 1762500570, 940695155, -1216823417] }, { "archive": 5, @@ -1682,12 +1037,7 @@ "name_hash": -1153234608, "name": "l48_56", "mapsquare": 12344, - "key": [ - 1004655261, - 1112441676, - -1346215742, - -481727651 - ] + "key": [1004655261, 1112441676, -1346215742, -481727651] }, { "archive": 5, @@ -1695,12 +1045,7 @@ "name_hash": -1153234607, "name": "l48_57", "mapsquare": 12345, - "key": [ - -1123116470, - -1886379076, - 75321832, - 214948598 - ] + "key": [-1123116470, -1886379076, 75321832, 214948598] }, { "archive": 5, @@ -1708,12 +1053,7 @@ "name_hash": -1153234606, "name": "l48_58", "mapsquare": 12346, - "key": [ - -715432683, - -1936681920, - -1020543828, - 1309349058 - ] + "key": [-715432683, -1936681920, -1020543828, 1309349058] }, { "archive": 5, @@ -1721,12 +1061,7 @@ "name_hash": -1153234605, "name": "l48_59", "mapsquare": 12347, - "key": [ - -1936094430, - -1392774395, - -458238889, - -1734657503 - ] + "key": [-1936094430, -1392774395, -458238889, -1734657503] }, { "archive": 5, @@ -1734,12 +1069,7 @@ "name_hash": -1153234583, "name": "l48_60", "mapsquare": 12348, - "key": [ - 1498945330, - -1007588865, - 989046743, - -1246005481 - ] + "key": [1498945330, -1007588865, 989046743, -1246005481] }, { "archive": 5, @@ -1747,12 +1077,7 @@ "name_hash": -1153383569, "name": "l43_50", "mapsquare": 11058, - "key": [ - 1248059648, - -909154233, - -2017783073, - -1490858018 - ] + "key": [1248059648, -909154233, -2017783073, -1490858018] }, { "archive": 5, @@ -1760,12 +1085,7 @@ "name_hash": -1153383566, "name": "l43_53", "mapsquare": 11061, - "key": [ - -1835613132, - -798666747, - 2068157339, - -2010441483 - ] + "key": [-1835613132, -798666747, 2068157339, -2010441483] }, { "archive": 5, @@ -1773,12 +1093,7 @@ "name_hash": -1153383564, "name": "l43_55", "mapsquare": 11063, - "key": [ - 230190523, - -541989310, - 756088519, - 651538143 - ] + "key": [230190523, -541989310, 756088519, 651538143] }, { "archive": 5, @@ -1786,12 +1101,7 @@ "name_hash": -1152281325, "name": "l59_48", "mapsquare": 15152, - "key": [ - 608495786, - -1850745649, - 1481459068, - 44047411 - ] + "key": [608495786, -1850745649, 1481459068, 44047411] }, { "archive": 5, @@ -1799,12 +1109,7 @@ "name_hash": -1154128366, "name": "l39_49", "mapsquare": 10033, - "key": [ - 1965668434, - 1587425243, - 966917721, - 2010341526 - ] + "key": [1965668434, 1587425243, 966917721, 2010341526] }, { "archive": 5, @@ -1812,12 +1117,7 @@ "name_hash": -1154128343, "name": "l39_51", "mapsquare": 10035, - "key": [ - -1407868267, - -2023338060, - 1465071532, - -1638236197 - ] + "key": [-1407868267, -2023338060, 1465071532, -1638236197] }, { "archive": 5, @@ -1825,12 +1125,7 @@ "name_hash": -1367450280, "name": "l52_152", "mapsquare": 13464, - "key": [ - -1367805857, - 1879344111, - -360193890, - -1649253702 - ] + "key": [-1367805857, 1879344111, -360193890, -1649253702] }, { "archive": 5, @@ -1838,12 +1133,7 @@ "name_hash": -1153383504, "name": "l43_73", "mapsquare": 11081, - "key": [ - -1262440825, - -866171020, - -669660830, - 1117529492 - ] + "key": [-1262440825, -866171020, -669660830, 1117529492] }, { "archive": 5, @@ -1851,12 +1141,7 @@ "name_hash": -1153383503, "name": "l43_74", "mapsquare": 11082, - "key": [ - -1048566284, - -1888694855, - 1387988701, - 1385807517 - ] + "key": [-1048566284, -1888694855, 1387988701, 1385807517] }, { "archive": 5, @@ -1864,12 +1149,7 @@ "name_hash": -1392385371, "name": "l46_149", "mapsquare": 11925, - "key": [ - -302404963, - 277321688, - 1579550568, - 112114901 - ] + "key": [-302404963, 277321688, 1579550568, 112114901] }, { "archive": 5, @@ -1877,12 +1157,7 @@ "name_hash": -1392385349, "name": "l46_150", "mapsquare": 11926, - "key": [ - 1068449903, - -150593625, - 336172166, - -629999737 - ] + "key": [1068449903, -150593625, 336172166, -629999737] }, { "archive": 5, @@ -1890,12 +1165,7 @@ "name_hash": -1392385347, "name": "l46_152", "mapsquare": 11928, - "key": [ - 926476326, - -742526377, - -1211115608, - -1389832255 - ] + "key": [926476326, -742526377, -1211115608, -1389832255] }, { "archive": 5, @@ -1903,12 +1173,7 @@ "name_hash": -1154128279, "name": "l39_73", "mapsquare": 10057, - "key": [ - 2098955587, - 1915815888, - -1487119512, - 2000380500 - ] + "key": [2098955587, 1915815888, -1487119512, 2000380500] }, { "archive": 5, @@ -1916,12 +1181,7 @@ "name_hash": -1392385346, "name": "l46_153", "mapsquare": 11929, - "key": [ - 1557493911, - -1795871852, - 842977119, - -1273925544 - ] + "key": [1557493911, -1795871852, 842977119, -1273925544] }, { "archive": 5, @@ -1929,12 +1189,7 @@ "name_hash": -1154128278, "name": "l39_74", "mapsquare": 10058, - "key": [ - -1722103890, - -365638741, - -1142855167, - 2038282466 - ] + "key": [-1722103890, -365638741, -1142855167, 2038282466] }, { "archive": 5, @@ -1942,12 +1197,7 @@ "name_hash": -1154128277, "name": "l39_75", "mapsquare": 10059, - "key": [ - 888791770, - 446863035, - 1420300298, - 1689801625 - ] + "key": [888791770, 446863035, 1420300298, 1689801625] }, { "archive": 5, @@ -1955,12 +1205,7 @@ "name_hash": -1155051771, "name": "l29_81", "mapsquare": 7505, - "key": [ - 1128826986, - -1208716500, - 1252781850, - 1529005118 - ] + "key": [1128826986, -1208716500, 1252781850, 1529005118] }, { "archive": 5, @@ -1968,12 +1213,7 @@ "name_hash": -1154277232, "name": "l34_75", "mapsquare": 8779, - "key": [ - -678956803, - 2085783757, - 650059580, - 1450034986 - ] + "key": [-678956803, 2085783757, 650059580, 1450034986] }, { "archive": 5, @@ -1981,12 +1221,7 @@ "name_hash": -1154366578, "name": "l31_81", "mapsquare": 8017, - "key": [ - 1937423379, - 797654757, - -418006613, - -1412491464 - ] + "key": [1937423379, 797654757, -418006613, -1412491464] }, { "archive": 5, @@ -1994,12 +1229,7 @@ "name_hash": -1390538330, "name": "l48_148", "mapsquare": 12436, - "key": [ - 399007290, - 768017220, - 1423287782, - -1886380141 - ] + "key": [399007290, 768017220, 1423287782, -1886380141] }, { "archive": 5, @@ -2007,12 +1237,7 @@ "name_hash": -1390538329, "name": "l48_149", "mapsquare": 12437, - "key": [ - -1441809522, - 719788383, - 401674935, - 735960337 - ] + "key": [-1441809522, 719788383, 401674935, 735960337] }, { "archive": 5, @@ -2020,12 +1245,7 @@ "name_hash": -1390538304, "name": "l48_153", "mapsquare": 12441, - "key": [ - -2117208237, - -719237621, - 1574397150, - 760135387 - ] + "key": [-2117208237, -719237621, 1574397150, 760135387] }, { "archive": 5, @@ -2033,12 +1253,7 @@ "name_hash": -1390538303, "name": "l48_154", "mapsquare": 12442, - "key": [ - 1291079634, - -1775973138, - -22379340, - -1049278279 - ] + "key": [1291079634, -1775973138, -22379340, -1049278279] }, { "archive": 5, @@ -2046,12 +1261,7 @@ "name_hash": -1390538302, "name": "l48_155", "mapsquare": 12443, - "key": [ - 185729295, - -1473640650, - 785055601, - 1540127286 - ] + "key": [185729295, -1473640650, 785055601, 1540127286] }, { "archive": 5, @@ -2059,12 +1269,7 @@ "name_hash": -1153324011, "name": "l45_47", "mapsquare": 11567, - "key": [ - 1608156752, - 653692997, - -1552888712, - -68059986 - ] + "key": [1608156752, 653692997, -1552888712, -68059986] }, { "archive": 5, @@ -2072,12 +1277,7 @@ "name_hash": -1153324010, "name": "l45_48", "mapsquare": 11568, - "key": [ - 1434739536, - -965821980, - 1477351656, - -1116923723 - ] + "key": [1434739536, -965821980, 1477351656, -1116923723] }, { "archive": 5, @@ -2085,12 +1285,7 @@ "name_hash": -1153323982, "name": "l45_55", "mapsquare": 11575, - "key": [ - -945127161, - -1910820945, - -1457442680, - -838340972 - ] + "key": [-945127161, -1910820945, -1457442680, -838340972] }, { "archive": 5, @@ -2098,12 +1293,7 @@ "name_hash": -1153323981, "name": "l45_56", "mapsquare": 11576, - "key": [ - -653186907, - 1743653193, - 1590707166, - 841079490 - ] + "key": [-653186907, 1743653193, 1590707166, 841079490] }, { "archive": 5, @@ -2111,12 +1301,7 @@ "name_hash": -1397002953, "name": "l41_151", "mapsquare": 10647, - "key": [ - -805201729, - 122084157, - -1599110597, - -1319888179 - ] + "key": [-805201729, 122084157, -1599110597, -1319888179] }, { "archive": 5, @@ -2124,12 +1309,7 @@ "name_hash": -1153472967, "name": "l40_46", "mapsquare": 10286, - "key": [ - 153699565, - -613131576, - -377838747, - -1493212656 - ] + "key": [153699565, -613131576, -377838747, -1493212656] }, { "archive": 5, @@ -2137,12 +1317,7 @@ "name_hash": -1153323979, "name": "l45_58", "mapsquare": 11578, - "key": [ - 899841295, - -1673793442, - -444221245, - -1412324058 - ] + "key": [899841295, -1673793442, -444221245, -1412324058] }, { "archive": 5, @@ -2150,12 +1325,7 @@ "name_hash": -1397002951, "name": "l41_153", "mapsquare": 10649, - "key": [ - -42874604, - 1755845042, - -28694142, - -1223794235 - ] + "key": [-42874604, 1755845042, -28694142, -1223794235] }, { "archive": 5, @@ -2163,12 +1333,7 @@ "name_hash": -1153323978, "name": "l45_59", "mapsquare": 11579, - "key": [ - -1812176752, - -317754254, - -1196521232, - -764437892 - ] + "key": [-1812176752, -317754254, -1196521232, -764437892] }, { "archive": 5, @@ -2176,12 +1341,7 @@ "name_hash": -1397002950, "name": "l41_154", "mapsquare": 10650, - "key": [ - 688979136, - 1749672831, - 630260962, - 1478721348 - ] + "key": [688979136, 1749672831, 630260962, 1478721348] }, { "archive": 5, @@ -2189,12 +1349,7 @@ "name_hash": -1153472964, "name": "l40_49", "mapsquare": 10289, - "key": [ - 661370115, - 1720102, - -155777581, - 1516736681 - ] + "key": [661370115, 1720102, -155777581, 1516736681] }, { "archive": 5, @@ -2202,12 +1357,7 @@ "name_hash": -1154217623, "name": "l36_81", "mapsquare": 9297, - "key": [ - -713608515, - -67472639, - -1826048194, - 544718437 - ] + "key": [-713608515, -67472639, -1826048194, 544718437] }, { "archive": 5, @@ -2215,12 +1365,7 @@ "name_hash": -1153472938, "name": "l40_54", "mapsquare": 10294, - "key": [ - -1453542294, - -12979792, - -48294325, - -2009299224 - ] + "key": [-1453542294, -12979792, -48294325, -2009299224] }, { "archive": 5, @@ -2228,12 +1373,7 @@ "name_hash": -1396079429, "name": "l42_154", "mapsquare": 10906, - "key": [ - 578750625, - -1699758530, - 981674787, - -1430062823 - ] + "key": [578750625, -1699758530, 981674787, -1430062823] }, { "archive": 5, @@ -2241,12 +1381,7 @@ "name_hash": -1152460043, "name": "l53_55", "mapsquare": 13623, - "key": [ - 1573282650, - -1418634195, - -1148095035, - -1144615238 - ] + "key": [1573282650, -1418634195, -1148095035, -1144615238] }, { "archive": 5, @@ -2254,12 +1389,7 @@ "name_hash": -1152400462, "name": "l55_54", "mapsquare": 14134, - "key": [ - -1102558063, - 817524163, - -892019492, - -1799662614 - ] + "key": [-1102558063, 817524163, -892019492, -1799662614] }, { "archive": 5, @@ -2267,12 +1397,7 @@ "name_hash": -1152430252, "name": "l54_55", "mapsquare": 13879, - "key": [ - -489064370, - 2145976597, - -1121899197, - 1908605309 - ] + "key": [-489064370, 2145976597, -1121899197, 1908605309] }, { "archive": 5, @@ -2280,12 +1405,7 @@ "name_hash": -1152430256, "name": "l54_51", "mapsquare": 13875, - "key": [ - 1430738652, - -42941568, - -775986981, - 1000814725 - ] + "key": [1430738652, -42941568, -775986981, 1000814725] }, { "archive": 5, @@ -2293,12 +1413,7 @@ "name_hash": -1152430255, "name": "l54_52", "mapsquare": 13876, - "key": [ - -225305190, - 2101410213, - -13023121, - 617681501 - ] + "key": [-225305190, 2101410213, -13023121, 617681501] }, { "archive": 5, @@ -2306,12 +1421,7 @@ "name_hash": -1396079456, "name": "l42_148", "mapsquare": 10900, - "key": [ - 305961345, - -1339000220, - 2053506211, - -1898778662 - ] + "key": [305961345, -1339000220, 2053506211, -1898778662] }, { "archive": 5, @@ -2319,12 +1429,7 @@ "name_hash": -1395155934, "name": "l43_149", "mapsquare": 11157, - "key": [ - 1464071264, - -103928758, - 1681823375, - -1178129652 - ] + "key": [1464071264, -103928758, 1681823375, -1178129652] }, { "archive": 5, @@ -2332,12 +1437,7 @@ "name_hash": -1154247442, "name": "l35_74", "mapsquare": 9034, - "key": [ - 385694264, - 2091635410, - 1191598764, - -2130030706 - ] + "key": [385694264, 2091635410, 1191598764, -2130030706] }, { "archive": 5, @@ -2345,12 +1445,7 @@ "name_hash": -1153353772, "name": "l44_56", "mapsquare": 11320, - "key": [ - -1608050593, - -413428259, - 2059848881, - -2038252682 - ] + "key": [-1608050593, -413428259, 2059848881, -2038252682] }, { "archive": 5, @@ -2358,12 +1453,7 @@ "name_hash": -1394232384, "name": "l44_157", "mapsquare": 11421, - "key": [ - 1786548109, - -823015733, - 1963056537, - -1997978489 - ] + "key": [1786548109, -823015733, 1963056537, -1997978489] }, { "archive": 5, @@ -2371,12 +1461,7 @@ "name_hash": -1153353771, "name": "l44_57", "mapsquare": 11321, - "key": [ - 1281968466, - -998167738, - 684914723, - -1121178555 - ] + "key": [1281968466, -998167738, 684914723, -1121178555] }, { "archive": 5, @@ -2384,12 +1469,7 @@ "name_hash": -1369297347, "name": "l50_148", "mapsquare": 12948, - "key": [ - 1629198458, - 696032791, - -1386317415, - 445054408 - ] + "key": [1629198458, 696032791, -1386317415, 445054408] }, { "archive": 5, @@ -2397,12 +1477,7 @@ "name_hash": -1154307113, "name": "l33_48", "mapsquare": 8496, - "key": [ - 1343253631, - 1982572295, - -1601521319, - 2107012341 - ] + "key": [1343253631, 1982572295, -1601521319, 2107012341] }, { "archive": 5, @@ -2410,12 +1485,7 @@ "name_hash": -1154307112, "name": "l33_49", "mapsquare": 8497, - "key": [ - 2127424498, - 1622469596, - -1889017351, - -1927651722 - ] + "key": [2127424498, 1622469596, -1889017351, -1927651722] }, { "archive": 5, @@ -2423,12 +1493,7 @@ "name_hash": -1154307090, "name": "l33_50", "mapsquare": 8498, - "key": [ - -1323684593, - -1102390619, - 1456317314, - -2027993898 - ] + "key": [-1323684593, -1102390619, 1456317314, -2027993898] }, { "archive": 5, @@ -2436,12 +1501,7 @@ "name_hash": -1154307089, "name": "l33_51", "mapsquare": 8499, - "key": [ - 1158999293, - 2131770333, - -861122128, - 1149793504 - ] + "key": [1158999293, 2131770333, -861122128, 1149793504] }, { "archive": 5, @@ -2449,12 +1509,7 @@ "name_hash": -1154277322, "name": "l34_48", "mapsquare": 8752, - "key": [ - 50858443, - 684152471, - 698071810, - -175585203 - ] + "key": [50858443, 684152471, 698071810, -175585203] }, { "archive": 5, @@ -2462,12 +1517,7 @@ "name_hash": -1154277298, "name": "l34_51", "mapsquare": 8755, - "key": [ - -1165798584, - 772244190, - -402783978, - 541755309 - ] + "key": [-1165798584, 772244190, -402783978, 541755309] }, { "archive": 5, @@ -2475,12 +1525,7 @@ "name_hash": -1154247531, "name": "l35_48", "mapsquare": 9008, - "key": [ - 2084752401, - -1394447522, - 2084945842, - 1474596929 - ] + "key": [2084752401, -1394447522, 2084945842, 1474596929] }, { "archive": 5, @@ -2488,12 +1533,7 @@ "name_hash": -1154247508, "name": "l35_50", "mapsquare": 9010, - "key": [ - 1975408960, - 888933152, - -1564560503, - 1102048305 - ] + "key": [1975408960, 888933152, -1564560503, 1102048305] }, { "archive": 5, @@ -2501,12 +1541,7 @@ "name_hash": -1154247507, "name": "l35_51", "mapsquare": 9011, - "key": [ - -135370293, - 700991137, - -1302596410, - -1183796338 - ] + "key": [-135370293, 700991137, -1302596410, -1183796338] }, { "archive": 5, @@ -2514,12 +1549,7 @@ "name_hash": -1154247506, "name": "l35_52", "mapsquare": 9012, - "key": [ - 1204696185, - -486414605, - -1016110497, - 134649113 - ] + "key": [1204696185, -486414605, -1016110497, 134649113] }, { "archive": 5, @@ -2527,12 +1557,7 @@ "name_hash": -1154217740, "name": "l36_48", "mapsquare": 9264, - "key": [ - 1166653059, - 1243560308, - 851316348, - -2052894389 - ] + "key": [1166653059, 1243560308, 851316348, -2052894389] }, { "archive": 5, @@ -2540,12 +1565,7 @@ "name_hash": -1154217716, "name": "l36_51", "mapsquare": 9267, - "key": [ - 245074215, - -415791406, - 175943925, - 572779390 - ] + "key": [245074215, -415791406, 175943925, 572779390] }, { "archive": 5, @@ -2553,12 +1573,7 @@ "name_hash": -1152370671, "name": "l56_54", "mapsquare": 14390, - "key": [ - -1631704360, - 1281079278, - -1549067757, - -2034268623 - ] + "key": [-1631704360, 1281079278, -1549067757, -2034268623] }, { "archive": 5, @@ -2566,12 +1581,7 @@ "name_hash": -1153472936, "name": "l40_56", "mapsquare": 10296, - "key": [ - 352471788, - -1609938193, - -266114897, - -1904210854 - ] + "key": [352471788, -1609938193, -266114897, -1904210854] }, { "archive": 5, @@ -2579,12 +1589,7 @@ "name_hash": -1153413353, "name": "l42_57", "mapsquare": 10809, - "key": [ - -256458821, - -522789093, - -547929725, - 1236572696 - ] + "key": [-256458821, -522789093, -547929725, 1236572696] }, { "archive": 5, @@ -2592,12 +1597,7 @@ "name_hash": -1153383562, "name": "l43_57", "mapsquare": 11065, - "key": [ - -1487802839, - 856470179, - 1889283583, - 1157865105 - ] + "key": [-1487802839, 856470179, 1889283583, 1157865105] }, { "archive": 5, @@ -2605,12 +1605,7 @@ "name_hash": -1153472935, "name": "l40_57", "mapsquare": 10297, - "key": [ - -465349039, - -896523889, - 319217459, - -1898915679 - ] + "key": [-465349039, -896523889, 319217459, -1898915679] }, { "archive": 5, @@ -2618,12 +1613,7 @@ "name_hash": -1153443143, "name": "l41_58", "mapsquare": 10554, - "key": [ - 1188457126, - -1729374406, - -799893645, - 1217674507 - ] + "key": [1188457126, -1729374406, -799893645, 1217674507] }, { "archive": 5, @@ -2631,12 +1621,7 @@ "name_hash": -1418243931, "name": "l39_156", "mapsquare": 10140, - "key": [ - 1403932265, - 753452087, - 1731472685, - -767209354 - ] + "key": [1403932265, 753452087, 1731472685, -767209354] }, { "archive": 5, @@ -2644,12 +1629,7 @@ "name_hash": -1154158129, "name": "l38_56", "mapsquare": 9784, - "key": [ - 1874487660, - 1635569708, - -1949316626, - -1920350613 - ] + "key": [1874487660, 1635569708, -1949316626, -1920350613] }, { "archive": 5, @@ -2657,12 +1637,7 @@ "name_hash": -1154158128, "name": "l38_57", "mapsquare": 9785, - "key": [ - -65486938, - -1485596203, - -1327236566, - 408455718 - ] + "key": [-65486938, -1485596203, -1327236566, 408455718] }, { "archive": 5, @@ -2670,12 +1645,7 @@ "name_hash": -1154128337, "name": "l39_57", "mapsquare": 10041, - "key": [ - 1187862613, - -117754960, - 130411769, - -1192628982 - ] + "key": [1187862613, -117754960, 130411769, -1192628982] }, { "archive": 5, @@ -2683,12 +1653,7 @@ "name_hash": -1154277230, "name": "l34_77", "mapsquare": 8781, - "key": [ - -1424107598, - 264936559, - -56759783, - -902529771 - ] + "key": [-1424107598, 264936559, -56759783, -902529771] }, { "archive": 5, @@ -2696,12 +1661,7 @@ "name_hash": -1154158104, "name": "l38_60", "mapsquare": 9788, - "key": [ - 432135203, - 92254316, - -1619550296, - 76065412 - ] + "key": [432135203, 92254316, -1619550296, 76065412] }, { "archive": 5, @@ -2709,12 +1669,7 @@ "name_hash": -1154128335, "name": "l39_59", "mapsquare": 10043, - "key": [ - 1912880022, - -1723964516, - 2062562401, - -1162129761 - ] + "key": [1912880022, -1723964516, 2062562401, -1162129761] }, { "archive": 5, @@ -2722,12 +1677,7 @@ "name_hash": -1153472910, "name": "l40_61", "mapsquare": 10301, - "key": [ - -158146381, - 1698585677, - -910760378, - 815929788 - ] + "key": [-158146381, 1698585677, -910760378, 815929788] }, { "archive": 5, @@ -2735,12 +1685,7 @@ "name_hash": -1153443119, "name": "l41_61", "mapsquare": 10557, - "key": [ - -807815903, - 958215082, - -647601710, - 1350072419 - ] + "key": [-807815903, 958215082, -647601710, 1350072419] }, { "archive": 5, @@ -2748,12 +1693,7 @@ "name_hash": -1153413389, "name": "l42_42", "mapsquare": 10794, - "key": [ - 311561230, - 1919568586, - -437925589, - -1702919060 - ] + "key": [311561230, 1919568586, -437925589, -1702919060] }, { "archive": 5, @@ -2761,12 +1701,7 @@ "name_hash": -1154187950, "name": "l37_47", "mapsquare": 9519, - "key": [ - 859829242, - 1044182946, - -1333414478, - 1254064132 - ] + "key": [859829242, 1044182946, -1333414478, 1254064132] }, { "archive": 5, @@ -2774,12 +1709,7 @@ "name_hash": -1154128336, "name": "l39_58", "mapsquare": 10042, - "key": [ - 736722071, - 75967325, - -775764394, - 106769937 - ] + "key": [736722071, 75967325, -775764394, 106769937] }, { "archive": 5, @@ -2787,12 +1717,7 @@ "name_hash": -1153413297, "name": "l42_71", "mapsquare": 10823, - "key": [ - -626951011, - -1729338061, - -758591782, - 439072305 - ] + "key": [-626951011, -1729338061, -758591782, 439072305] }, { "archive": 5, @@ -2800,12 +1725,7 @@ "name_hash": -1395155904, "name": "l43_158", "mapsquare": 11166, - "key": [ - 431616711, - -1774935949, - -1016388232, - -1018749983 - ] + "key": [431616711, -1774935949, -1016388232, -1018749983] }, { "archive": 5, @@ -2813,12 +1733,7 @@ "name_hash": -1395155903, "name": "l43_159", "mapsquare": 11167, - "key": [ - -1959015492, - -1104071, - -1016386588, - 1365103001 - ] + "key": [-1959015492, -1104071, -1016386588, 1365103001] }, { "archive": 5, @@ -2826,12 +1741,7 @@ "name_hash": -1153383561, "name": "l43_58", "mapsquare": 11066, - "key": [ - 291008624, - -1992710142, - -1831766032, - 1925022398 - ] + "key": [291008624, -1992710142, -1831766032, 1925022398] }, { "archive": 5, @@ -2839,12 +1749,7 @@ "name_hash": -1153383560, "name": "l43_59", "mapsquare": 11067, - "key": [ - 1192664190, - -341042618, - -820464572, - 602716622 - ] + "key": [1192664190, -341042618, -820464572, 602716622] }, { "archive": 5, @@ -2852,12 +1757,7 @@ "name_hash": -1153383538, "name": "l43_60", "mapsquare": 11068, - "key": [ - 1956851882, - 1582504141, - -1090835806, - 1413275925 - ] + "key": [1956851882, 1582504141, -1090835806, 1413275925] }, { "archive": 5, @@ -2865,12 +1765,7 @@ "name_hash": -1153413329, "name": "l42_60", "mapsquare": 10812, - "key": [ - 90198727, - 258723745, - 748197903, - -426406231 - ] + "key": [90198727, 258723745, 748197903, -426406231] }, { "archive": 5, @@ -2878,12 +1773,7 @@ "name_hash": -1365603237, "name": "l54_153", "mapsquare": 13977, - "key": [ - 692126287, - 1949546323, - -1604362290, - -896929747 - ] + "key": [692126287, 1949546323, -1604362290, -896929747] }, { "archive": 5, @@ -2891,12 +1781,7 @@ "name_hash": -1152400465, "name": "l55_51", "mapsquare": 14131, - "key": [ - 1016975630, - -301160039, - -1036603507, - 114074749 - ] + "key": [1016975630, -301160039, -1036603507, 114074749] }, { "archive": 5, @@ -2904,12 +1789,7 @@ "name_hash": -1397002977, "name": "l41_148", "mapsquare": 10644, - "key": [ - -1850188218, - -1521064184, - 1993643055, - -554430753 - ] + "key": [-1850188218, -1521064184, 1993643055, -554430753] }, { "archive": 5, @@ -2917,12 +1797,7 @@ "name_hash": -1365603235, "name": "l54_155", "mapsquare": 13979, - "key": [ - 1489416025, - -1142280467, - 1808198885, - 137033499 - ] + "key": [1489416025, -1142280467, 1808198885, 137033499] }, { "archive": 5, @@ -2930,12 +1805,7 @@ "name_hash": -1364679714, "name": "l55_155", "mapsquare": 14235, - "key": [ - 2114439316, - -345963084, - -1331796597, - 275182841 - ] + "key": [2114439316, -345963084, -1331796597, 275182841] }, { "archive": 5, @@ -2943,12 +1813,7 @@ "name_hash": -1364679715, "name": "l55_154", "mapsquare": 14234, - "key": [ - 237295045, - 867264725, - -1732973561, - -1010980224 - ] + "key": [237295045, 867264725, -1732973561, -1010980224] }, { "archive": 5, @@ -2956,12 +1821,7 @@ "name_hash": -1153472902, "name": "l40_69", "mapsquare": 10309, - "key": [ - 1450418080, - -2118438156, - -1409971045, - -1573015729 - ] + "key": [1450418080, -2118438156, -1409971045, -1573015729] }, { "archive": 5, @@ -2969,12 +1829,7 @@ "name_hash": -1152370670, "name": "l56_55", "mapsquare": 14391, - "key": [ - 956732210, - 1669781219, - 1907068552, - -1303552057 - ] + "key": [956732210, 1669781219, 1907068552, -1303552057] }, { "archive": 5, @@ -2982,12 +1837,7 @@ "name_hash": -1152340880, "name": "l57_54", "mapsquare": 14646, - "key": [ - -1240067889, - -383570142, - -558581485, - 786219832 - ] + "key": [-1240067889, -383570142, -558581485, 786219832] }, { "archive": 5, @@ -2995,12 +1845,7 @@ "name_hash": -1152340879, "name": "l57_55", "mapsquare": 14647, - "key": [ - -1420591871, - -1781801975, - 1517176402, - -1599286074 - ] + "key": [-1420591871, -1781801975, 1517176402, -1599286074] }, { "archive": 5, @@ -3008,12 +1853,7 @@ "name_hash": -1154187887, "name": "l37_68", "mapsquare": 9540, - "key": [ - 2133656685, - -1448323734, - -310319541, - -725382856 - ] + "key": [2133656685, -1448323734, -310319541, -725382856] }, { "archive": 5, @@ -3021,12 +1861,7 @@ "name_hash": -1154187857, "name": "l37_77", "mapsquare": 9549, - "key": [ - 1895759075, - -843340286, - 1429492719, - 295020002 - ] + "key": [1895759075, -843340286, 1429492719, 295020002] }, { "archive": 5, @@ -3034,12 +1869,7 @@ "name_hash": -1154128275, "name": "l39_77", "mapsquare": 10061, - "key": [ - -99111554, - 1883772725, - 1465462119, - 1523468364 - ] + "key": [-99111554, 1883772725, 1465462119, 1523468364] }, { "archive": 5, @@ -3047,12 +1877,7 @@ "name_hash": -1394232382, "name": "l44_159", "mapsquare": 11423, - "key": [ - 1414693295, - -863955294, - -2034093411, - 1818980885 - ] + "key": [1414693295, -863955294, -2034093411, 1818980885] }, { "archive": 5, @@ -3060,12 +1885,7 @@ "name_hash": -1393308862, "name": "l45_158", "mapsquare": 11678, - "key": [ - 350404025, - 770298785, - 1215100269, - -965606935 - ] + "key": [350404025, 770298785, 1215100269, -965606935] }, { "archive": 5, @@ -3073,12 +1893,7 @@ "name_hash": -1152430279, "name": "l54_49", "mapsquare": 13873, - "key": [ - -1098656620, - -1288920207, - 1465590763, - 1004731135 - ] + "key": [-1098656620, -1288920207, 1465590763, 1004731135] }, { "archive": 5, @@ -3086,12 +1901,7 @@ "name_hash": -1153353769, "name": "l44_59", "mapsquare": 11323, - "key": [ - -1788142439, - -1669893367, - 1168059730, - -14615580 - ] + "key": [-1788142439, -1669893367, 1168059730, -14615580] }, { "archive": 5, @@ -3099,12 +1909,7 @@ "name_hash": -1390538307, "name": "l48_150", "mapsquare": 12438, - "key": [ - 1545165254, - 945298048, - 244672985, - -2058714291 - ] + "key": [1545165254, 945298048, 244672985, -2058714291] }, { "archive": 5, @@ -3112,12 +1917,7 @@ "name_hash": -1390538306, "name": "l48_151", "mapsquare": 12439, - "key": [ - 737806768, - -1467792108, - 1644942216, - -2040381961 - ] + "key": [737806768, -1467792108, 1644942216, -2040381961] }, { "archive": 5, @@ -3125,12 +1925,7 @@ "name_hash": -1152549448, "name": "l50_44", "mapsquare": 12844, - "key": [ - 2093476291, - -208179048, - 86110726, - -3825057 - ] + "key": [2093476291, -208179048, 86110726, -3825057] }, { "archive": 5, @@ -3138,12 +1933,7 @@ "name_hash": -1152519657, "name": "l51_44", "mapsquare": 13100, - "key": [ - -1830823075, - 1215145937, - -525456385, - -257417215 - ] + "key": [-1830823075, 1215145937, -525456385, -257417215] }, { "archive": 5, @@ -3151,12 +1941,7 @@ "name_hash": -1154247443, "name": "l35_73", "mapsquare": 9033, - "key": [ - -340750931, - -1897990035, - 1835646040, - 1466647905 - ] + "key": [-340750931, -1897990035, 1835646040, 1466647905] }, { "archive": 5, @@ -3164,12 +1949,7 @@ "name_hash": -1364679718, "name": "l55_151", "mapsquare": 14231, - "key": [ - 1658757346, - -2019485271, - -1955365006, - 895906099 - ] + "key": [1658757346, -2019485271, -1955365006, 895906099] }, { "archive": 5, @@ -3177,12 +1957,7 @@ "name_hash": -1154217741, "name": "l36_47", "mapsquare": 9263, - "key": [ - -937938813, - 1777088166, - 1291736808, - 1827292190 - ] + "key": [-937938813, 1777088166, 1291736808, 1827292190] }, { "archive": 5, @@ -3190,12 +1965,7 @@ "name_hash": -1155051796, "name": "l29_77", "mapsquare": 7501, - "key": [ - 1108184632, - 2136992911, - -832195021, - 495111280 - ] + "key": [1108184632, 2136992911, -832195021, 495111280] }, { "archive": 5, @@ -3203,12 +1973,7 @@ "name_hash": -1418243929, "name": "l39_158", "mapsquare": 10142, - "key": [ - 1872120942, - -765842959, - 449655176, - -1168971827 - ] + "key": [1872120942, -765842959, 449655176, -1168971827] }, { "archive": 5, @@ -3216,12 +1981,7 @@ "name_hash": -1419167450, "name": "l38_158", "mapsquare": 9886, - "key": [ - -1621103539, - 1580907615, - -2010887870, - 683082929 - ] + "key": [-1621103539, 1580907615, -2010887870, 683082929] }, { "archive": 5, @@ -3229,12 +1989,7 @@ "name_hash": -1154396394, "name": "l30_77", "mapsquare": 7757, - "key": [ - -1928468960, - 1136494639, - -1967058052, - 602105509 - ] + "key": [-1928468960, 1136494639, -1967058052, 602105509] }, { "archive": 5, @@ -3242,12 +1997,7 @@ "name_hash": -1154187833, "name": "l37_80", "mapsquare": 9552, - "key": [ - 1401891457, - -1899495202, - -773917688, - 1780158441 - ] + "key": [1401891457, -1899495202, -773917688, 1780158441] }, { "archive": 5, @@ -3255,12 +2005,7 @@ "name_hash": -1154158042, "name": "l38_80", "mapsquare": 9808, - "key": [ - -923585668, - -574638285, - 500509980, - -960811077 - ] + "key": [-923585668, -574638285, 500509980, -960811077] }, { "archive": 5, @@ -3268,12 +2013,7 @@ "name_hash": -1154366604, "name": "l31_76", "mapsquare": 8012, - "key": [ - -1309713498, - 82935011, - -1681291522, - -685742249 - ] + "key": [-1309713498, 82935011, -1681291522, -685742249] }, { "archive": 5, @@ -3281,12 +2021,7 @@ "name_hash": -1155051803, "name": "l29_70", "mapsquare": 7494, - "key": [ - -462058213, - -2060727055, - 781172327, - 1942354602 - ] + "key": [-462058213, -2060727055, 781172327, 1942354602] }, { "archive": 5, @@ -3294,12 +2029,7 @@ "name_hash": -1154187855, "name": "l37_79", "mapsquare": 9551, - "key": [ - 1566715405, - -1011565479, - -979871653, - -2050870795 - ] + "key": [1566715405, -1011565479, -979871653, -2050870795] }, { "archive": 5, @@ -3307,12 +2037,7 @@ "name_hash": -1152460072, "name": "l53_47", "mapsquare": 13615, - "key": [ - 1478333842, - -146576907, - -285634093, - 361637473 - ] + "key": [1478333842, -146576907, -285634093, 361637473] }, { "archive": 5, @@ -3320,12 +2045,7 @@ "name_hash": -1154306997, "name": "l33_80", "mapsquare": 8528, - "key": [ - -1141049958, - 1626814655, - 206252937, - 924426084 - ] + "key": [-1141049958, 1626814655, 206252937, 924426084] }, { "archive": 5, @@ -3333,12 +2053,7 @@ "name_hash": -1155051826, "name": "l29_68", "mapsquare": 7492, - "key": [ - -342030979, - 1222986839, - 511788549, - 910172876 - ] + "key": [-342030979, 1222986839, 511788549, 910172876] }, { "archive": 5, @@ -3346,12 +2061,7 @@ "name_hash": -1154396424, "name": "l30_68", "mapsquare": 7748, - "key": [ - 1860227470, - -290409954, - 274550911, - -1155783956 - ] + "key": [1860227470, -290409954, 274550911, -1155783956] }, { "archive": 5, @@ -3359,12 +2069,7 @@ "name_hash": -1154396398, "name": "l30_73", "mapsquare": 7753, - "key": [ - 1896168736, - -1223044138, - 779149869, - -1759332197 - ] + "key": [1896168736, -1223044138, 779149869, -1759332197] }, { "archive": 5, @@ -3372,12 +2077,7 @@ "name_hash": -1397002954, "name": "l41_150", "mapsquare": 10646, - "key": [ - 1341282074, - 345412696, - -2043666158, - -457216576 - ] + "key": [1341282074, 345412696, -2043666158, -457216576] }, { "archive": 5, @@ -3385,12 +2085,7 @@ "name_hash": -1152460073, "name": "l53_46", "mapsquare": 13614, - "key": [ - -1661089893, - 60198635, - 829308397, - -1835163720 - ] + "key": [-1661089893, 60198635, 829308397, -1835163720] }, { "archive": 5, @@ -3398,12 +2093,7 @@ "name_hash": -1367450304, "name": "l52_149", "mapsquare": 13461, - "key": [ - -126183647, - -25151941, - 868809662, - 1423445530 - ] + "key": [-126183647, -25151941, 868809662, 1423445530] }, { "archive": 5, @@ -3411,12 +2101,7 @@ "name_hash": -1389614784, "name": "l49_152", "mapsquare": 12696, - "key": [ - 1955953194, - -1456762745, - -1903871849, - -1325043037 - ] + "key": [1955953194, -1456762745, -1903871849, -1325043037] }, { "archive": 5, @@ -3424,12 +2109,7 @@ "name_hash": -1153264340, "name": "l47_73", "mapsquare": 12105, - "key": [ - 1153497516, - -449169462, - -635419798, - -1471828315 - ] + "key": [1153497516, -449169462, -635419798, -1471828315] }, { "archive": 5, @@ -3437,12 +2117,7 @@ "name_hash": -1152489866, "name": "l52_44", "mapsquare": 13356, - "key": [ - -62403158, - -259993960, - 1312599048, - 602862976 - ] + "key": [-62403158, -259993960, 1312599048, 602862976] }, { "archive": 5, @@ -3450,12 +2125,7 @@ "name_hash": -1153204849, "name": "l49_45", "mapsquare": 12589, - "key": [ - 1867222552, - -1279268543, - 219776982, - -1133356510 - ] + "key": [1867222552, -1279268543, 219776982, -1133356510] }, { "archive": 5, @@ -3463,12 +2133,7 @@ "name_hash": -1154396393, "name": "l30_78", "mapsquare": 7758, - "key": [ - -623741461, - -108703380, - 1436176787, - -834745239 - ] + "key": [-623741461, -108703380, 1436176787, -834745239] }, { "archive": 5, @@ -3476,12 +2141,7 @@ "name_hash": -1153294225, "name": "l46_42", "mapsquare": 11818, - "key": [ - -2034608097, - 1147002393, - -720701760, - -1045127369 - ] + "key": [-2034608097, 1147002393, -720701760, -1045127369] }, { "archive": 5, @@ -3489,12 +2149,7 @@ "name_hash": -1155111353, "name": "l27_81", "mapsquare": 6993, - "key": [ - 487810245, - -1442562976, - -1813756859, - 201393142 - ] + "key": [487810245, -1442562976, -1813756859, 201393142] }, { "archive": 5, @@ -3502,12 +2157,7 @@ "name_hash": -1155081594, "name": "l28_70", "mapsquare": 7238, - "key": [ - -853120516, - 1697831503, - -12188711, - 770411534 - ] + "key": [-853120516, 1697831503, -12188711, 770411534] }, { "archive": 5, @@ -3515,12 +2165,7 @@ "name_hash": -1392385372, "name": "l46_148", "mapsquare": 11924, - "key": [ - 1132625310, - 132067456, - -328236024, - 510687418 - ] + "key": [1132625310, 132067456, -328236024, 510687418] }, { "archive": 5, @@ -3528,12 +2173,7 @@ "name_hash": -1154158096, "name": "l38_68", "mapsquare": 9796, - "key": [ - -392461938, - 562137949, - 1796705877, - -650819019 - ] + "key": [-392461938, 562137949, 1796705877, -650819019] }, { "archive": 5, @@ -3541,12 +2181,7 @@ "name_hash": -1152400488, "name": "l55_49", "mapsquare": 14129, - "key": [ - 2079314312, - -89031344, - 495299597, - -2042107512 - ] + "key": [2079314312, -89031344, 495299597, -2042107512] }, { "archive": 5, @@ -3554,12 +2189,7 @@ "name_hash": -1152400466, "name": "l55_50", "mapsquare": 14130, - "key": [ - 1237228106, - -349369148, - -1811607373, - -882226393 - ] + "key": [1237228106, -349369148, -1811607373, -882226393] }, { "archive": 5, @@ -3567,12 +2197,7 @@ "name_hash": -1365603240, "name": "l54_150", "mapsquare": 13974, - "key": [ - -606147120, - 1392509835, - -1748925993, - -2005068147 - ] + "key": [-606147120, 1392509835, -1748925993, -2005068147] }, { "archive": 5, @@ -3580,12 +2205,7 @@ "name_hash": -1153353715, "name": "l44_71", "mapsquare": 11335, - "key": [ - -133492081, - -915358326, - -714649892, - -2093709476 - ] + "key": [-133492081, -915358326, -714649892, -2093709476] }, { "archive": 5, @@ -3593,12 +2213,7 @@ "name_hash": -1153294102, "name": "l46_81", "mapsquare": 11857, - "key": [ - -1225499683, - -2000595018, - -612194825, - -2014162349 - ] + "key": [-1225499683, -2000595018, -612194825, -2014162349] }, { "archive": 5, @@ -3606,12 +2221,7 @@ "name_hash": -1368373800, "name": "l51_153", "mapsquare": 13209, - "key": [ - -795447804, - 1305344381, - 98581556, - 2008745861 - ] + "key": [-795447804, 1305344381, 98581556, 2008745861] }, { "archive": 5, @@ -3619,12 +2229,7 @@ "name_hash": -1153264311, "name": "l47_81", "mapsquare": 12113, - "key": [ - 1668148064, - 1058673313, - -1746348692, - 847341704 - ] + "key": [1668148064, 1058673313, -1746348692, 847341704] }, { "archive": 5, @@ -3632,12 +2237,7 @@ "name_hash": -1153234520, "name": "l48_81", "mapsquare": 12369, - "key": [ - -832628753, - 1107609195, - 262567666, - -1274474550 - ] + "key": [-832628753, 1107609195, 262567666, -1274474550] }, { "archive": 5, @@ -3645,12 +2245,7 @@ "name_hash": -1154247501, "name": "l35_57", "mapsquare": 9017, - "key": [ - -518439975, - -1388520826, - 203536985, - 1155539914 - ] + "key": [-518439975, -1388520826, 203536985, 1155539914] }, { "archive": 5, @@ -3658,12 +2253,7 @@ "name_hash": -1152430251, "name": "l54_56", "mapsquare": 13880, - "key": [ - -672032867, - -104766980, - -780173326, - -1476119873 - ] + "key": [-672032867, -104766980, -780173326, -1476119873] }, { "archive": 5, @@ -3671,12 +2261,7 @@ "name_hash": -1152400489, "name": "l55_48", "mapsquare": 14128, - "key": [ - 1907787432, - -241593923, - 1152767085, - -541422403 - ] + "key": [1907787432, -241593923, 1152767085, -541422403] }, { "archive": 5, @@ -3684,12 +2269,7 @@ "name_hash": -1152400460, "name": "l55_56", "mapsquare": 14136, - "key": [ - -1104533465, - 1792124817, - -1564247177, - 79706641 - ] + "key": [-1104533465, 1792124817, -1564247177, 79706641] }, { "archive": 5, @@ -3697,12 +2277,7 @@ "name_hash": -1152370669, "name": "l56_56", "mapsquare": 14392, - "key": [ - 993603906, - -1477196579, - 593064486, - 166369140 - ] + "key": [993603906, -1477196579, 593064486, 166369140] }, { "archive": 5, @@ -3710,12 +2285,7 @@ "name_hash": -1152340878, "name": "l57_56", "mapsquare": 14648, - "key": [ - -1757352130, - -1996516705, - 263017190, - 1647356258 - ] + "key": [-1757352130, -1996516705, 263017190, 1647356258] }, { "archive": 5, @@ -3723,12 +2293,7 @@ "name_hash": -1152311088, "name": "l58_55", "mapsquare": 14903, - "key": [ - -1111240831, - 1790345264, - -366658712, - -331374702 - ] + "key": [-1111240831, 1790345264, -366658712, -331374702] }, { "archive": 5, @@ -3736,12 +2301,7 @@ "name_hash": -1152311087, "name": "l58_56", "mapsquare": 14904, - "key": [ - -1967472485, - -192437954, - 1186759929, - -2078112945 - ] + "key": [-1967472485, -192437954, 1186759929, -2078112945] }, { "archive": 5, @@ -3749,12 +2309,7 @@ "name_hash": -1152281298, "name": "l59_54", "mapsquare": 15158, - "key": [ - -974248920, - -1426940984, - -551894435, - 1783499939 - ] + "key": [-974248920, -1426940984, -551894435, 1783499939] }, { "archive": 5, @@ -3762,12 +2317,7 @@ "name_hash": -1152281296, "name": "l59_56", "mapsquare": 15160, - "key": [ - -553466395, - -1372948696, - -1385390322, - 710626387 - ] + "key": [-553466395, -1372948696, -1385390322, 710626387] }, { "archive": 5, @@ -3775,12 +2325,7 @@ "name_hash": -1153264309, "name": "l47_83", "mapsquare": 12115, - "key": [ - 2146362785, - 1996258091, - -613445101, - 539756591 - ] + "key": [2146362785, 1996258091, -613445101, 539756591] }, { "archive": 5, @@ -3788,12 +2333,7 @@ "name_hash": -1154336814, "name": "l32_75", "mapsquare": 8267, - "key": [ - -474856962, - -1295973639, - 789657650, - -1769058462 - ] + "key": [-474856962, -1295973639, 789657650, -1769058462] }, { "archive": 5, @@ -3801,12 +2341,7 @@ "name_hash": -1154217677, "name": "l36_69", "mapsquare": 9285, - "key": [ - -1376572370, - -121986361, - -1862348009, - -378224358 - ] + "key": [-1376572370, -121986361, -1862348009, -378224358] }, { "archive": 5, @@ -3814,12 +2349,7 @@ "name_hash": -1151625926, "name": "l60_45", "mapsquare": 15405, - "key": [ - 1745315296, - 704015968, - -1726703759, - 250744336 - ] + "key": [1745315296, 704015968, -1726703759, 250744336] }, { "archive": 5, @@ -3827,12 +2357,7 @@ "name_hash": -1151625925, "name": "l60_46", "mapsquare": 15406, - "key": [ - 900232781, - 1037303290, - 2099698517, - -1839409134 - ] + "key": [900232781, 1037303290, 2099698517, -1839409134] }, { "archive": 5, @@ -3840,12 +2365,7 @@ "name_hash": -1151625924, "name": "l60_47", "mapsquare": 15407, - "key": [ - -1139819812, - 165771634, - 462281145, - -1626973480 - ] + "key": [-1139819812, 165771634, 462281145, -1626973480] }, { "archive": 5, @@ -3853,12 +2373,7 @@ "name_hash": -1155111376, "name": "l27_79", "mapsquare": 6991, - "key": [ - -1448188175, - 626198836, - 1985989165, - -1062391664 - ] + "key": [-1448188175, 626198836, 1985989165, -1062391664] }, { "archive": 5, @@ -3866,12 +2381,7 @@ "name_hash": -1155081585, "name": "l28_79", "mapsquare": 7247, - "key": [ - -122734679, - -1029771956, - 1633683499, - 846700218 - ] + "key": [-122734679, -1029771956, 1633683499, 846700218] }, { "archive": 5, @@ -3879,12 +2389,7 @@ "name_hash": -1154277290, "name": "l34_59", "mapsquare": 8763, - "key": [ - -161594592, - -1041269457, - 871932542, - -908444460 - ] + "key": [-161594592, -1041269457, 871932542, -908444460] }, { "archive": 5, @@ -3892,12 +2397,7 @@ "name_hash": -1154336872, "name": "l32_59", "mapsquare": 8251, - "key": [ - 1142567601, - 1650263019, - 49659607, - -899246535 - ] + "key": [1142567601, 1650263019, 49659607, -899246535] }, { "archive": 5, @@ -3905,12 +2405,7 @@ "name_hash": -1154307082, "name": "l33_58", "mapsquare": 8506, - "key": [ - -1227747958, - 1491928866, - 1293676120, - 2065870654 - ] + "key": [-1227747958, 1491928866, 1293676120, 2065870654] }, { "archive": 5, @@ -3918,12 +2413,7 @@ "name_hash": -1154307081, "name": "l33_59", "mapsquare": 8507, - "key": [ - 1765022148, - -80255262, - -725852452, - -1286377093 - ] + "key": [1765022148, -80255262, -725852452, -1286377093] }, { "archive": 5, @@ -3931,12 +2421,7 @@ "name_hash": -1154277292, "name": "l34_57", "mapsquare": 8761, - "key": [ - 1760753095, - -1427813077, - 266675077, - -255782653 - ] + "key": [1760753095, -1427813077, 266675077, -255782653] }, { "archive": 5, @@ -3944,12 +2429,7 @@ "name_hash": -1154277291, "name": "l34_58", "mapsquare": 8762, - "key": [ - -1868090282, - -1544166661, - -731821081, - 1736861342 - ] + "key": [-1868090282, -1544166661, -731821081, 1736861342] }, { "archive": 5, @@ -3957,12 +2437,7 @@ "name_hash": -1154277268, "name": "l34_60", "mapsquare": 8764, - "key": [ - 1880374454, - 1213514336, - -2078057600, - -2021473694 - ] + "key": [1880374454, 1213514336, -2078057600, -2021473694] }, { "archive": 5, @@ -3970,12 +2445,7 @@ "name_hash": -1154277267, "name": "l34_61", "mapsquare": 8765, - "key": [ - 1948979312, - 134066799, - -78879371, - -323055687 - ] + "key": [1948979312, 134066799, -78879371, -323055687] }, { "archive": 5, @@ -3983,12 +2453,7 @@ "name_hash": -1154247499, "name": "l35_59", "mapsquare": 9019, - "key": [ - -1293726217, - -1696419000, - -859948399, - 1059527576 - ] + "key": [-1293726217, -1696419000, -859948399, 1059527576] }, { "archive": 5, @@ -3996,12 +2461,7 @@ "name_hash": -1154247477, "name": "l35_60", "mapsquare": 9020, - "key": [ - -1906040194, - 849367381, - 2098246444, - 1605043698 - ] + "key": [-1906040194, 849367381, 2098246444, 1605043698] }, { "archive": 5, @@ -4009,12 +2469,7 @@ "name_hash": -1154247476, "name": "l35_61", "mapsquare": 9021, - "key": [ - -665917952, - -432697139, - -602494723, - -2097936281 - ] + "key": [-665917952, -432697139, -602494723, -2097936281] }, { "archive": 5, @@ -4022,12 +2477,7 @@ "name_hash": -1153472973, "name": "l40_40", "mapsquare": 10280, - "key": [ - -1245893544, - -118079793, - -1624599660, - -626968532 - ] + "key": [-1245893544, -118079793, -1624599660, -626968532] }, { "archive": 5, @@ -4035,12 +2485,7 @@ "name_hash": -1153472972, "name": "l40_41", "mapsquare": 10281, - "key": [ - 2129832996, - -1542613289, - -1612399066, - -323592936 - ] + "key": [2129832996, -1542613289, -1612399066, -323592936] }, { "archive": 5, @@ -4048,12 +2493,7 @@ "name_hash": -1153472971, "name": "l40_42", "mapsquare": 10282, - "key": [ - 667792020, - 292003472, - -998896147, - 7080342 - ] + "key": [667792020, 292003472, -998896147, 7080342] }, { "archive": 5, @@ -4061,12 +2501,7 @@ "name_hash": -1153413391, "name": "l42_40", "mapsquare": 10792, - "key": [ - -125671574, - 254943715, - 1343095705, - -1965171670 - ] + "key": [-125671574, 254943715, 1343095705, -1965171670] }, { "archive": 5, @@ -4074,12 +2509,7 @@ "name_hash": -1153413328, "name": "l42_61", "mapsquare": 10813, - "key": [ - 78604466, - -1582607088, - 691011324, - -1155733133 - ] + "key": [78604466, -1582607088, 691011324, -1155733133] }, { "archive": 5, @@ -4087,12 +2517,7 @@ "name_hash": -1153383537, "name": "l43_61", "mapsquare": 11069, - "key": [ - 281072607, - -1791037221, - -1221626554, - 801634958 - ] + "key": [281072607, -1791037221, -1221626554, 801634958] }, { "archive": 5, @@ -4100,12 +2525,7 @@ "name_hash": -1154158071, "name": "l38_72", "mapsquare": 9800, - "key": [ - 1648231074, - -690523856, - 538076864, - -489360965 - ] + "key": [1648231074, -690523856, 538076864, -489360965] }, { "archive": 5, @@ -4113,12 +2533,7 @@ "name_hash": -1154307021, "name": "l33_77", "mapsquare": 8525, - "key": [ - 1448703859, - 604202172, - 1058795271, - -80742538 - ] + "key": [1448703859, 604202172, 1058795271, -80742538] }, { "archive": 5, @@ -4126,12 +2541,7 @@ "name_hash": -1154217742, "name": "l36_46", "mapsquare": 9262, - "key": [ - -1327237404, - -257519940, - -1398355053, - -970581711 - ] + "key": [-1327237404, -257519940, -1398355053, -970581711] }, { "archive": 5, @@ -4139,12 +2549,7 @@ "name_hash": -1154187951, "name": "l37_46", "mapsquare": 9518, - "key": [ - -557639005, - 398566091, - -133936467, - -850662847 - ] + "key": [-557639005, 398566091, -133936467, -850662847] }, { "archive": 5, @@ -4152,12 +2557,7 @@ "name_hash": -1153472970, "name": "l40_43", "mapsquare": 10283, - "key": [ - -2133080221, - 1327669620, - 173304076, - -151662318 - ] + "key": [-2133080221, 1327669620, 173304076, -151662318] }, { "archive": 5, @@ -4165,12 +2565,7 @@ "name_hash": -1153294226, "name": "l46_41", "mapsquare": 11817, - "key": [ - 740863947, - -1459447536, - -1272357052, - -1730407126 - ] + "key": [740863947, -1459447536, -1272357052, -1730407126] }, { "archive": 5, @@ -4178,12 +2573,7 @@ "name_hash": -1153294224, "name": "l46_43", "mapsquare": 11819, - "key": [ - -1632272271, - -1134214079, - -1204220834, - -1633494895 - ] + "key": [-1632272271, -1134214079, -1204220834, -1633494895] }, { "archive": 5, @@ -4191,12 +2581,7 @@ "name_hash": -1152460042, "name": "l53_56", "mapsquare": 13624, - "key": [ - 2075882635, - 144612382, - -11140999, - 1068051873 - ] + "key": [2075882635, 144612382, -11140999, 1068051873] }, { "archive": 5, @@ -4204,12 +2589,7 @@ "name_hash": -1152460041, "name": "l53_57", "mapsquare": 13625, - "key": [ - -1688194808, - -751145145, - -64310690, - -9400824 - ] + "key": [-1688194808, -751145145, -64310690, -9400824] }, { "archive": 5, @@ -4217,12 +2597,7 @@ "name_hash": -1152460040, "name": "l53_58", "mapsquare": 13626, - "key": [ - 2091552269, - -19993197, - 919014338, - -2088295508 - ] + "key": [2091552269, -19993197, 919014338, -2088295508] }, { "archive": 5, @@ -4230,12 +2605,7 @@ "name_hash": -1152460039, "name": "l53_59", "mapsquare": 13627, - "key": [ - 341129543, - 405594157, - -935930552, - 1362472171 - ] + "key": [341129543, 405594157, -935930552, 1362472171] }, { "archive": 5, @@ -4243,12 +2613,7 @@ "name_hash": -1152460017, "name": "l53_60", "mapsquare": 13628, - "key": [ - 83847925, - -1748584368, - -1828230097, - 915424426 - ] + "key": [83847925, -1748584368, -1828230097, 915424426] }, { "archive": 5, @@ -4256,12 +2621,7 @@ "name_hash": -1152460016, "name": "l53_61", "mapsquare": 13629, - "key": [ - -1526659316, - 194744161, - -1617203167, - 1822755797 - ] + "key": [-1526659316, 194744161, -1617203167, 1822755797] }, { "archive": 5, @@ -4269,12 +2629,7 @@ "name_hash": -1152460015, "name": "l53_62", "mapsquare": 13630, - "key": [ - -1632016999, - -2015192780, - -2137722473, - 477794767 - ] + "key": [-1632016999, -2015192780, -2137722473, 477794767] }, { "archive": 5, @@ -4282,12 +2637,7 @@ "name_hash": -1154187862, "name": "l37_72", "mapsquare": 9544, - "key": [ - 1190108828, - -1694672329, - 922227461, - 627710655 - ] + "key": [1190108828, -1694672329, 922227461, 627710655] }, { "archive": 5, @@ -4295,12 +2645,7 @@ "name_hash": -1152400464, "name": "l55_52", "mapsquare": 14132, - "key": [ - 1385901079, - -1626256839, - 2140816760, - -1871930940 - ] + "key": [1385901079, -1626256839, 2140816760, -1871930940] }, { "archive": 5, @@ -4308,12 +2653,7 @@ "name_hash": -1363756198, "name": "l56_150", "mapsquare": 14486, - "key": [ - 801004021, - 788873243, - -1673638404, - 152435782 - ] + "key": [801004021, 788873243, -1673638404, 152435782] }, { "archive": 5, @@ -4321,12 +2661,7 @@ "name_hash": -1152370675, "name": "l56_50", "mapsquare": 14386, - "key": [ - -1730596947, - 85732186, - -1776102738, - -2096470688 - ] + "key": [-1730596947, 85732186, -1776102738, -2096470688] }, { "archive": 5, @@ -4334,12 +2669,7 @@ "name_hash": -1152370674, "name": "l56_51", "mapsquare": 14387, - "key": [ - -327431537, - -279720677, - 1848501675, - 306634513 - ] + "key": [-327431537, -279720677, 1848501675, 306634513] }, { "archive": 5, @@ -4347,12 +2677,7 @@ "name_hash": -1152370673, "name": "l56_52", "mapsquare": 14388, - "key": [ - 1061380274, - -429796323, - -221565610, - -967547362 - ] + "key": [1061380274, -429796323, -221565610, -967547362] }, { "archive": 5, @@ -4360,12 +2685,7 @@ "name_hash": -1154217646, "name": "l36_79", "mapsquare": 9295, - "key": [ - -128031646, - -1131908397, - -1360861665, - 1112176197 - ] + "key": [-128031646, -1131908397, -1360861665, 1112176197] }, { "archive": 5, @@ -4373,12 +2693,7 @@ "name_hash": -1154396370, "name": "l30_80", "mapsquare": 7760, - "key": [ - 2042192998, - 743878512, - -1804236758, - -1160501924 - ] + "key": [2042192998, 743878512, -1804236758, -1160501924] }, { "archive": 5, @@ -4386,12 +2701,7 @@ "name_hash": -1396079428, "name": "l42_155", "mapsquare": 10907, - "key": [ - 1703225431, - -1175749730, - 1842579622, - -1861290070 - ] + "key": [1703225431, -1175749730, 1842579622, -1861290070] }, { "archive": 5, @@ -4399,11 +2709,6 @@ "name_hash": -1155051797, "name": "l29_76", "mapsquare": 7500, - "key": [ - -1016974560, - 452375550, - 1138391999, - 85568702 - ] + "key": [-1016974560, 452375550, 1138391999, 85568702] } ] diff --git a/data/config/xteas/468.json b/data/config/xteas/468.json index b3063f30d..e3a966f46 100644 --- a/data/config/xteas/468.json +++ b/data/config/xteas/468.json @@ -5,12 +5,7 @@ "name_hash": -1155051794, "name": "l29_79", "mapsquare": 7503, - "key": [ - -205505693, - -1069477933, - -1042446848, - -93348110 - ] + "key": [-205505693, -1069477933, -1042446848, -93348110] }, { "archive": 5, @@ -18,11 +13,6 @@ "name_hash": -1154396392, "name": "l30_79", "mapsquare": 7759, - "key": [ - -1255219039, - -277284099, - 1886972034, - -723091074 - ] + "key": [-1255219039, -277284099, 1886972034, -723091074] } ] diff --git a/jest.config.ts b/jest.config.ts index ca16247c1..3a4d0bb80 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -4,202 +4,196 @@ */ export default { - // All imported modules in your tests should be mocked automatically - // automock: false, + // All imported modules in your tests should be mocked automatically + // automock: false, - // Stop running tests after `n` failures - // bail: 0, + // Stop running tests after `n` failures + // bail: 0, - // The directory where Jest should store its cached dependency information - // cacheDirectory: "C:\\Users\\james\\AppData\\Local\\Temp\\jest", + // The directory where Jest should store its cached dependency information + // cacheDirectory: "C:\\Users\\james\\AppData\\Local\\Temp\\jest", - // Automatically clear mock calls, instances, contexts and results before every test - clearMocks: true, + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: true, + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, - // An array of glob patterns indicating a set of files for which coverage information should be collected - // collectCoverageFrom: undefined, + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, - // The directory where Jest should output its coverage files - coverageDirectory: "coverage", + // The directory where Jest should output its coverage files + coverageDirectory: 'coverage', - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "\\\\node_modules\\\\" - // ], - roots: [ - '/src' - ], + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + roots: ['/src'], - moduleNameMapper: { - '@engine/(.*)': '/src/engine/$1', - '@server/(.*)': '/src/server/$1', - '@plugins/(.*)': '/src/plugins/$1', - }, + moduleNameMapper: { + '@engine/(.*)': '/src/engine/$1', + '@server/(.*)': '/src/server/$1', + '@plugins/(.*)': '/src/plugins/$1', + }, + // Indicates which provider should be used to instrument code for coverage + // coverageProvider: "babel", + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], - // Indicates which provider should be used to instrument code for coverage - // coverageProvider: "babel", + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], + // A path to a custom dependency extractor + // dependencyExtractor: undefined, - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: undefined, + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, - // A path to a custom dependency extractor - // dependencyExtractor: undefined, + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], - // The default configuration for fake timers - // fakeTimers: { - // "enableGlobally": false - // }, + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, + // A set of global variables that need to be available in all test environments + // globals: {}, - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: undefined, + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", - // A set of global variables that need to be available in all test environments - // globals: {}, + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - // maxWorkers: "50%", + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], - // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "mjs", - // "cjs", - // "jsx", - // "ts", - // "tsx", - // "json", - // "node" - // ], + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], - // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: {}, + // Activates notifications for test results + // notify: false, - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", - // Activates notifications for test results - // notify: false, + // A preset that is used as a base for Jest's configuration + preset: 'ts-jest', - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", + // Run tests from one or more projects + // projects: undefined, - // A preset that is used as a base for Jest's configuration - preset: 'ts-jest', + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, - // Run tests from one or more projects - // projects: undefined, + // Automatically reset mock state before every test + // resetMocks: false, - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, + // Reset the module registry before running each individual test + // resetModules: false, - // Automatically reset mock state before every test - // resetMocks: false, + // A path to a custom resolver + // resolver: undefined, - // Reset the module registry before running each individual test - // resetModules: false, + // Automatically restore mock state and implementation before every test + // restoreMocks: false, - // A path to a custom resolver - // resolver: undefined, + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, - // Automatically restore mock state and implementation before every test - // restoreMocks: false, + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], - // The root directory that Jest should scan for tests and modules within - // rootDir: undefined, + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, - // A list of paths to modules that run some code to configure or set up the testing framework before each test - // setupFilesAfterEnv: [], + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], - // The number of seconds after which a test is considered as slow and reported as such in the results. - // slowTestThreshold: 5, + // The test environment that will be used for testing + testEnvironment: 'node', - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, - // The test environment that will be used for testing - testEnvironment: "node", + // Adds a location field to test results + // testLocationInResults: false, - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, + // The glob patterns Jest uses to detect test files + testMatch: ['**/*.test.ts'], - // Adds a location field to test results - // testLocationInResults: false, + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], - // The glob patterns Jest uses to detect test files - testMatch: [ - "**/*.test.ts" - ], + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "\\\\node_modules\\\\" - // ], + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", - // This option allows the use of a custom results processor - // testResultsProcessor: undefined, + // A map from regular expressions to paths to transformers + // transform: undefined, - // This option allows use of a custom test runner - // testRunner: "jest-circus/runner", + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "\\\\node_modules\\\\", + // "\\.pnp\\.[^\\\\]+$" + // ], - // A map from regular expressions to paths to transformers - // transform: undefined, + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "\\\\node_modules\\\\", - // "\\.pnp\\.[^\\\\]+$" - // ], + // Indicates whether each individual test should be reported during the run + // verbose: undefined, - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], - // Indicates whether each individual test should be reported during the run - // verbose: undefined, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, + // Whether to use watchman for file crawling + // watchman: true, }; diff --git a/nodemon.json b/nodemon.json index 14b7898fb..889ff16d5 100644 --- a/nodemon.json +++ b/nodemon.json @@ -3,4 +3,4 @@ "ignore": ["src/plugins/"], "watch": ["src/"], "ext": "ts, js" -} \ No newline at end of file +} diff --git a/package.json b/package.json index 7c7c7b7b5..0c90cbc68 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,7 @@ "type": "git", "url": "git+ssh://git@github.com/runejs/server.git" }, - "keywords": [ - "runejs", - "runescape", - "typescript", - "game server", - "game engine" - ], + "keywords": ["runejs", "runescape", "typescript", "game server", "game engine"], "author": "Tynarus", "license": "GPL-3.0", "bugs": { diff --git a/src/engine/action/action-pipeline.ts b/src/engine/action/action-pipeline.ts index cc349b7bf..97fa2913b 100644 --- a/src/engine/action/action-pipeline.ts +++ b/src/engine/action/action-pipeline.ts @@ -10,19 +10,15 @@ import type { Subscription } from 'rxjs'; */ export type ActionStrength = 'weak' | 'normal' | 'strong'; - /** * Content action type definitions. */ export type ActionType = - 'button' + | 'button' | 'widget_interaction' - | 'npc_init' | 'npc_interaction' - | 'object_interaction' - | 'item_interaction' | 'item_on_object' | 'item_on_npc' @@ -32,11 +28,9 @@ export type ActionType = | 'item_swap' | 'move_item' | 'spawned_item_interaction' - | 'magic_on_item' | 'magic_on_player' | 'magic_on_npc' - | 'player_init' | 'player_command' | 'player_interaction' @@ -44,24 +38,21 @@ export type ActionType = | 'equipment_change' | 'prayer'; - export const gentleActions: ActionType[] = [ - 'button', 'widget_interaction', 'player_init', 'npc_init', - 'move_item', 'item_swap', 'player_command', 'region_change' + 'button', + 'widget_interaction', + 'player_init', + 'npc_init', + 'move_item', + 'item_swap', + 'player_command', + 'region_change', ]; - /** * Methods in which action hooks in progress may be cancelled. */ -export type ActionCancelType = - 'manual-movement' - | 'pathing-movement' - | 'generic' - | 'keep-widgets-open' - | 'button' - | 'widget'; - +export type ActionCancelType = 'manual-movement' | 'pathing-movement' | 'generic' | 'keep-widgets-open' | 'button' | 'widget'; /** * The definition for the actual action pipe handler function. @@ -71,8 +62,7 @@ export type ActionPipeHandler = (...args: any[]) => RunnableHooks | void; /** * Basic definition of a game engine action file (.action.ts exports). */ -export type ActionPipe = [ ActionType, ActionPipeHandler ]; - +export type ActionPipe = [ActionType, ActionPipeHandler]; /** * A list of filtered hooks for an actor to run. @@ -84,13 +74,11 @@ export interface RunnableHooks { hooks?: ActionHook[]; } - /** * A specific actor's action pipeline handler. * Records action pipes and distributes content actions from the game engine down to execute plugin hooks. */ export class ActionPipeline { - private static pipes = new Map(); private runningTasks: TaskExecutor[] = []; @@ -98,8 +86,7 @@ export class ActionPipeline { private movementSubscription: Subscription; public constructor(public readonly actor: Actor) { - this.movementSubscription = this.actor.walkingQueue.movementQueued$ - .subscribe(async () => this.cancelRunningTasks()); + this.movementSubscription = this.actor.walkingQueue.movementQueued$.subscribe(async () => this.cancelRunningTasks()); } public static getPipe(action: ActionType): ActionPipeHandler | null { @@ -116,11 +103,11 @@ export class ActionPipeline { public async call(action: ActionType, ...args: any[]): Promise { const actionHandler = ActionPipeline.pipes.get(action.toString()); - if(actionHandler) { + if (actionHandler) { try { await this.runActionHandler(actionHandler, args); - } catch(error) { - if(error) { + } catch (error) { + if (error) { logger.error(`Error handling action ${action.toString()}`); logger.error(error); } @@ -129,14 +116,14 @@ export class ActionPipeline { } public async cancelRunningTasks(): Promise { - if(this.canceling || !this.runningTasks || this.runningTasks.length === 0) { + if (this.canceling || !this.runningTasks || this.runningTasks.length === 0) { return; } this.canceling = true; - for(const runningTask of this.runningTasks) { - if(runningTask.running) { + for (const runningTask of this.runningTasks) { + if (runningTask.running) { await runningTask.stop(); } } @@ -149,23 +136,23 @@ export class ActionPipeline { private async runActionHandler(actionHandler: any, args: any[]): Promise { const runnableHooks: RunnableHooks | null | undefined = await actionHandler(...args); - if(!runnableHooks?.hooks || runnableHooks.hooks.length === 0) { + if (!runnableHooks?.hooks || runnableHooks.hooks.length === 0) { return; } - for(let i = 0; i < runnableHooks.hooks.length; i++) { + for (let i = 0; i < runnableHooks.hooks.length; i++) { const hook = runnableHooks.hooks[i]; - if(!hook) { + if (!hook) { continue; } // Some actions are non-cancelling - if(gentleActions.indexOf(hook.type) === -1) { + if (gentleActions.indexOf(hook.type) === -1) { await this.cancelRunningTasks(); } await this.runHook(hook, runnableHooks.action); - if(!hook.multi) { + if (!hook.multi) { // If the highest priority hook does not allow other hooks // to run during this same action, then return here to break // out of the loop and complete execution. @@ -177,7 +164,7 @@ export class ActionPipeline { private async runHook(actionHook: ActionHook, action: any): Promise { const { handler, task } = actionHook; - if(task) { + if (task) { // Schedule task-based hook const taskExecutor = new TaskExecutor(this.actor, task, actionHook, action); this.runningTasks.push(taskExecutor); @@ -187,23 +174,22 @@ export class ActionPipeline { // Cleanup and remove the task once completed const taskIdx = this.runningTasks.findIndex(task => task.taskId === taskExecutor.taskId); - if(taskIdx !== -1) { + if (taskIdx !== -1) { this.runningTasks.splice(taskIdx, 1); } - } else if(handler) { + } else if (handler) { // Run basic hook await handler(action); } } public get paused(): boolean { - if(isPlayer(this.actor)) { - if(this.actor.interfaceState.widgetOpen()) { + if (isPlayer(this.actor)) { + if (this.actor.interfaceState.widgetOpen()) { return true; } } return false; } - } diff --git a/src/engine/action/hook/action-hook.ts b/src/engine/action/hook/action-hook.ts index c92100fdf..00bbc86b5 100644 --- a/src/engine/action/hook/action-hook.ts +++ b/src/engine/action/hook/action-hook.ts @@ -12,7 +12,6 @@ export interface QuestRequirement { stages?: number[]; } - /** * Defines a generic extensible game content action hook. */ @@ -33,7 +32,6 @@ export interface ActionHook { task?: HookTask; } - /** * Fetches the list of all discovered action hooks of the specified type. * @param actionType The Action Type to find the hook for. @@ -41,13 +39,12 @@ export interface ActionHook { */ export const getActionHooks = (actionType: ActionType, filter?: (actionHook: T) => boolean): T[] => { const hooks = actionHookMap[actionType] as T[]; - if(!hooks || hooks.length === 0) { + if (!hooks || hooks.length === 0) { return []; } return filter ? hooks.filter(filter) : hooks; -} - +}; /** * A sorter function that action hooks can be run through. @@ -55,5 +52,5 @@ export const getActionHooks = (actionType: ActionType, fil * @param actionHooks The list of hooks to sort. */ export function sortActionHooks(actionHooks: ActionHook[]): ActionHook[] { - return actionHooks.sort(actionHook => actionHook.questRequirement !== undefined ? -1 : 1); + return actionHooks.sort(actionHook => (actionHook.questRequirement !== undefined ? -1 : 1)); } diff --git a/src/engine/action/hook/hook-filters.test.ts b/src/engine/action/hook/hook-filters.test.ts index a3ecc8839..ecfceb9a4 100644 --- a/src/engine/action/hook/hook-filters.test.ts +++ b/src/engine/action/hook/hook-filters.test.ts @@ -1,30 +1,29 @@ -import { advancedNumberHookFilter } from './hook-filters' +import { advancedNumberHookFilter } from './hook-filters'; describe('action/hook hook filters', () => { describe('advancedNumberHookFilter', () => { - describe('when expected is a number array', () => { - const expected = [ 1, 2, 3 ] + const expected = [1, 2, 3]; describe('when input is in the array', () => { - const input = 2 + const input = 2; test('should return true', () => { - const result = advancedNumberHookFilter(expected, input) + const result = advancedNumberHookFilter(expected, input); - expect(result).toEqual(true) - }) - }) + expect(result).toEqual(true); + }); + }); describe('when input is not in the array', () => { - const input = 999 + const input = 999; test('should return false', () => { - const result = advancedNumberHookFilter(expected, input) - - expect(result).toEqual(false) - }) - }) - }) - }) -}) + const result = advancedNumberHookFilter(expected, input); + + expect(result).toEqual(false); + }); + }); + }); + }); +}); diff --git a/src/engine/action/hook/hook-filters.ts b/src/engine/action/hook/hook-filters.ts index 6b3e004a5..99594b399 100644 --- a/src/engine/action/hook/hook-filters.ts +++ b/src/engine/action/hook/hook-filters.ts @@ -2,12 +2,12 @@ import type { ActionHook } from '@engine/action/hook/action-hook'; import type { Player } from '@engine/world/actor/player/player'; export const stringHookFilter = (expected: string | string[], input: string): boolean => { - if(Array.isArray(expected)) { - if(expected.indexOf(input) === -1) { + if (Array.isArray(expected)) { + if (expected.indexOf(input) === -1) { return false; } } else { - if(expected !== input) { + if (expected !== input) { return false; } } @@ -15,14 +15,13 @@ export const stringHookFilter = (expected: string | string[], input: string): bo return true; }; - export const numberHookFilter = (expected: number | number[], input: number): boolean => { - if(Array.isArray(expected)) { - if(expected.indexOf(input) === -1) { + if (Array.isArray(expected)) { + if (expected.indexOf(input) === -1) { return false; } } else { - if(expected !== input) { + if (expected !== input) { return false; } } @@ -30,23 +29,26 @@ export const numberHookFilter = (expected: number | number[], input: number): bo return true; }; - -export const advancedNumberHookFilter = (expected: number | number[], input: number, options?: string | string[], - searchOption?: string): boolean => { - if(expected !== undefined) { - if(Array.isArray(expected)) { - if(expected.indexOf(input) === -1) { +export const advancedNumberHookFilter = ( + expected: number | number[], + input: number, + options?: string | string[], + searchOption?: string, +): boolean => { + if (expected !== undefined) { + if (Array.isArray(expected)) { + if (expected.indexOf(input) === -1) { return false; } } else { - if(expected !== input) { + if (expected !== input) { return false; } } } - if(options !== undefined && searchOption !== undefined) { - if(Array.isArray(options)) { + if (options !== undefined && searchOption !== undefined) { + if (Array.isArray(options)) { return options.indexOf(searchOption) !== -1; } else { return options === searchOption; @@ -56,35 +58,34 @@ export const advancedNumberHookFilter = (expected: number | number[], input: num } }; - /** * A quest requirement filter for hooks that uses the hook's `questRequirements` object. * @param player The player involved with the hook. * @param actionHook The action hook definition to filter. */ export function questHookFilter(player: Player, actionHook: ActionHook): boolean { - if(!actionHook.questRequirement) { + if (!actionHook.questRequirement) { return true; } const questId = actionHook.questRequirement.questId; const playerQuest = player.quests.find(quest => quest.questId === questId); - if(!playerQuest) { + if (!playerQuest) { // @TODO quest requirements return actionHook.questRequirement.stage === 0; } - if(actionHook.questRequirement.stage === 'complete') { + if (actionHook.questRequirement.stage === 'complete') { return playerQuest.progress === 'complete'; } - if(typeof playerQuest.progress === 'number') { - if(actionHook.questRequirement.stage !== undefined) { - if(!numberHookFilter(actionHook.questRequirement.stage, playerQuest.progress)) { + if (typeof playerQuest.progress === 'number') { + if (actionHook.questRequirement.stage !== undefined) { + if (!numberHookFilter(actionHook.questRequirement.stage, playerQuest.progress)) { return false; } - } else if(actionHook.questRequirement.stages !== undefined) { - if(!numberHookFilter(actionHook.questRequirement.stages, playerQuest.progress)) { + } else if (actionHook.questRequirement.stages !== undefined) { + if (!numberHookFilter(actionHook.questRequirement.stages, playerQuest.progress)) { return false; } } diff --git a/src/engine/action/hook/task.ts b/src/engine/action/hook/task.ts index cb213dfd0..8cdd3bde8 100644 --- a/src/engine/action/hook/task.ts +++ b/src/engine/action/hook/task.ts @@ -1,21 +1,19 @@ -import { v4 } from 'uuid'; import type { Subscription } from 'rxjs'; import { lastValueFrom, timer } from 'rxjs'; +import { v4 } from 'uuid'; import { logger } from '@runejs/common'; -import { isNpc, isPlayer } from '@engine/world/actor/util'; +import type { ActionStrength } from '@engine/action/action-pipeline'; +import type { ActionHook } from '@engine/action/hook/action-hook'; import type { Actor } from '@engine/world/actor/actor'; -import type { Player } from '@engine/world/actor/player/player'; import type { Npc } from '@engine/world/actor/npc'; -import type { ActionStrength } from '@engine/action/action-pipeline'; +import type { Player } from '@engine/world/actor/player/player'; +import { isNpc, isPlayer } from '@engine/world/actor/util'; import { World } from '@engine/world/world'; -import type { ActionHook } from '@engine/action/hook/action-hook'; - export type TaskSessionData = { [key: string]: any }; - export interface TaskDetails { actor: Actor; player: Player | undefined; @@ -24,7 +22,6 @@ export interface TaskDetails { session: TaskSessionData; } - export interface HookTask { canActivate?: (task: TaskExecutor, iteration?: number) => boolean | Promise; activate: (task: TaskExecutor, iteration?: number) => void | undefined | boolean | Promise; @@ -32,13 +29,11 @@ export interface HookTask { delay?: number; // # of ticks before execution delayMs?: number; // # of milliseconds before execution interval?: number; // # of ticks between loop intervals (defaults to single run task) - intervalMs?: number; // # of milliseconds between loop intervals (defaults to single run task) + intervalMs?: number; // # of milliseconds between loop intervals (defaults to single run task) } - // T = current action info (ButtonAction, MoveItemAction, etc) export class TaskExecutor { - public readonly taskId = v4(); public readonly strength: ActionStrength; public running: boolean = false; @@ -47,30 +42,30 @@ export class TaskExecutor { private iteration: number = 0; private intervalSubscription: Subscription; - public constructor(public readonly actor: Actor, - public readonly task: HookTask, - public readonly hook: ActionHook, - public readonly actionData: T) { + public constructor( + public readonly actor: Actor, + public readonly task: HookTask, + public readonly hook: ActionHook, + public readonly actionData: T, + ) { this.strength = this.hook.strength || 'normal'; } public async run(): Promise { this.running = true; - if(!!this.task.delay || !!this.task.delayMs) { - await lastValueFrom(timer(this.task.delayMs !== undefined ? this.task.delayMs : - (this.task.delay! * World.TICK_LENGTH))); + if (!!this.task.delay || !!this.task.delayMs) { + await lastValueFrom(timer(this.task.delayMs !== undefined ? this.task.delayMs : this.task.delay! * World.TICK_LENGTH)); } - if(!!this.task.interval || !!this.task.intervalMs) { + if (!!this.task.interval || !!this.task.intervalMs) { // Looping execution task - const intervalMs = this.task.intervalMs !== undefined ? this.task.intervalMs : - (this.task.interval! * World.TICK_LENGTH); + const intervalMs = this.task.intervalMs !== undefined ? this.task.intervalMs : this.task.interval! * World.TICK_LENGTH; await new Promise(resolve => { this.intervalSubscription = timer(0, intervalMs).subscribe( - async() => { - if(!await this.execute()) { + async () => { + if (!(await this.execute())) { this.intervalSubscription?.unsubscribe(); resolve(); } @@ -79,35 +74,36 @@ export class TaskExecutor { logger.error(error); resolve(); }, - () => resolve()); + () => resolve(), + ); }); } else { // Single execution task await this.execute(); } - if(this.running) { + if (this.running) { await this.stop(); } } public async execute(): Promise { - if(!this.actor) { + if (!this.actor) { // Actor destroyed, cancel the task return false; } - if(!await this.canActivate()) { + if (!(await this.canActivate())) { // Unable to activate the task, cancel return false; } - if(this.actor.actionPipeline.paused) { + if (this.actor.actionPipeline.paused) { // Action paused, continue loop if applicable return true; } - if(!this.running) { + if (!this.running) { // Task no longer running, cancel execution return false; } @@ -115,7 +111,7 @@ export class TaskExecutor { try { const response = await this.task.activate(this, this.iteration++); return typeof response === 'boolean' ? response : true; - } catch(error) { + } catch (error) { logger.error(`Error executing action task`); logger.error(error); return false; @@ -123,17 +119,17 @@ export class TaskExecutor { } public async canActivate(): Promise { - if(!this.valid) { + if (!this.valid) { return false; } - if(!this.task.canActivate) { + if (!this.task.canActivate) { return true; } try { return this.task.canActivate(this, this.iteration); - } catch(error) { + } catch (error) { logger.error(`Error calling action canActivate`, this.task); logger.error(error); return false; @@ -144,7 +140,7 @@ export class TaskExecutor { this.running = false; this.intervalSubscription?.unsubscribe(); - if(this.task?.onComplete) { + if (this.task?.onComplete) { await this.task.onComplete(this, this.iteration); } } @@ -155,12 +151,11 @@ export class TaskExecutor { player: isPlayer(this.actor) ? this.actor : undefined, npc: isNpc(this.actor) ? this.actor : undefined, actionData: this.actionData, - session: this.session + session: this.session, }; } public get valid(): boolean { return !!this.task?.activate && !!this.actionData; } - } diff --git a/src/engine/action/loader.ts b/src/engine/action/loader.ts index deee7778b..8421d40c9 100644 --- a/src/engine/action/loader.ts +++ b/src/engine/action/loader.ts @@ -1,10 +1,9 @@ +import { join } from 'path'; import type { ActionPipe } from '@engine/action/action-pipeline'; import { ActionPipeline } from '@engine/action/action-pipeline'; import { BUILD_DIR } from '@engine/config/directories'; import { getFiles } from '@engine/util/files'; import { logger } from '@runejs/common'; -import { join } from 'path'; - /** * Finds and loads all available action pipe files (`*.action.ts`). @@ -15,8 +14,8 @@ export async function loadActionFiles(): Promise { const blacklist = []; const loadedActions: string[] = []; - for await(const path of getFiles(PIPE_DIRECTORY, blacklist)) { - if(!path.endsWith('.action.ts') && !path.endsWith('.action.js')) { + for await (const path of getFiles(PIPE_DIRECTORY, blacklist)) { + if (!path.endsWith('.action.ts') && !path.endsWith('.action.js')) { continue; } @@ -24,11 +23,11 @@ export async function loadActionFiles(): Promise { try { const importedAction = (require(location)?.default || null) as ActionPipe | null; - if(importedAction && Array.isArray(importedAction) && importedAction[0] && importedAction[1]) { + if (importedAction && Array.isArray(importedAction) && importedAction[0] && importedAction[1]) { ActionPipeline.register(importedAction[0], importedAction[1]); loadedActions.push(importedAction[0]); } - } catch(error) { + } catch (error) { logger.error(`Error loading action file at ${location}:`); logger.error(error); } diff --git a/src/engine/action/pipe/button.action.ts b/src/engine/action/pipe/button.action.ts index 2fa28229a..417b375ef 100644 --- a/src/engine/action/pipe/button.action.ts +++ b/src/engine/action/pipe/button.action.ts @@ -1,5 +1,5 @@ import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; -import { getActionHooks, type ActionHook } from '@engine/action/hook/action-hook'; +import { type ActionHook, getActionHooks } from '@engine/action/hook/action-hook'; import { advancedNumberHookFilter, questHookFilter } from '@engine/action/hook/hook-filters'; import type { Player } from '@engine/world/actor/player/player'; @@ -17,13 +17,11 @@ export interface ButtonActionHook extends ActionHook void | Promise; - /** * Details about a button action being performed. */ @@ -36,7 +34,6 @@ export interface ButtonAction { buttonId: number; } - /** * The pipe that the game engine hands button actions off to. * @param player @@ -44,23 +41,21 @@ export interface ButtonAction { * @param buttonId */ const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): RunnableHooks | null => { - let matchingHooks = getActionHooks('button') - .filter(plugin => - questHookFilter(player, plugin) && ( - (plugin.widgetId && plugin.widgetId === widgetId) || - (plugin.widgetIds && advancedNumberHookFilter(plugin.widgetIds, widgetId) - )) - && (plugin.buttonIds === undefined || - advancedNumberHookFilter(plugin.buttonIds, buttonId)) - ); + let matchingHooks = getActionHooks('button').filter( + plugin => + questHookFilter(player, plugin) && + ((plugin.widgetId && plugin.widgetId === widgetId) || + (plugin.widgetIds && advancedNumberHookFilter(plugin.widgetIds, widgetId))) && + (plugin.buttonIds === undefined || advancedNumberHookFilter(plugin.buttonIds, buttonId)), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { + if (matchingHooks.length === 0) { player.outgoingPackets.chatboxMessage(`Unhandled button interaction: ${widgetId}:${buttonId}`); return null; } @@ -68,13 +63,14 @@ const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): R return { hooks: matchingHooks, action: { - player, widgetId, buttonId - } + player, + widgetId, + buttonId, + }, }; }; - /** * Button action pipe definition. */ -export default [ 'button', buttonActionPipe ] as ActionPipe; +export default ['button', buttonActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/equipment-change.action.ts b/src/engine/action/pipe/equipment-change.action.ts index 072b759ab..b8263072d 100644 --- a/src/engine/action/pipe/equipment-change.action.ts +++ b/src/engine/action/pipe/equipment-change.action.ts @@ -1,9 +1,9 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, numberHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; +import { numberHookFilter, questHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; import { findItem } from '@engine/config/config-handler'; -import type { ItemDetails, EquipmentSlot } from '@engine/config/item-config'; +import type { EquipmentSlot, ItemDetails } from '@engine/config/item-config'; import type { Player } from '@engine/world/actor/player/player'; import { logger } from '@runejs/common'; @@ -17,19 +17,16 @@ export interface EquipmentChangeActionHook extends ActionHook void; - /** * Equipment action types. */ export type EquipmentChangeType = 'equip' | 'unequip'; - /** * Details about an item being equipped/unequipped. */ @@ -46,7 +43,6 @@ export interface EquipmentChangeAction { equipmentSlot: EquipmentSlot; } - /** * The pipe that the game engine hands equipment actions off to. * @param player @@ -54,22 +50,25 @@ export interface EquipmentChangeAction { * @param eventType * @param slot */ -const equipmentChangeActionPipe = (player: Player, itemId: number, - eventType: EquipmentChangeType, slot: EquipmentSlot): RunnableHooks | null => { +const equipmentChangeActionPipe = ( + player: Player, + itemId: number, + eventType: EquipmentChangeType, + slot: EquipmentSlot, +): RunnableHooks | null => { let matchingHooks = getActionHooks('equipment_change', equipActionHook => { - if(!questHookFilter(player, equipActionHook)) { + if (!questHookFilter(player, equipActionHook)) { return false; } - if(equipActionHook.itemIds !== undefined) { - if(!numberHookFilter(equipActionHook.itemIds, itemId)) { + if (equipActionHook.itemIds !== undefined) { + if (!numberHookFilter(equipActionHook.itemIds, itemId)) { return false; } } - - if(equipActionHook.eventType !== undefined) { - if(!stringHookFilter(equipActionHook.eventType, eventType)) { + if (equipActionHook.eventType !== undefined) { + if (!stringHookFilter(equipActionHook.eventType, eventType)) { return false; } } @@ -78,17 +77,17 @@ const equipmentChangeActionPipe = (player: Player, itemId: number, const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(!matchingHooks || matchingHooks.length === 0) { + if (!matchingHooks || matchingHooks.length === 0) { return null; } const itemDetails = findItem(itemId); - if(!itemDetails) { + if (!itemDetails) { logger.error(`Item ${itemId} not registered on the server [equipment-change action pipe]`); return null; } @@ -100,13 +99,12 @@ const equipmentChangeActionPipe = (player: Player, itemId: number, itemId, itemDetails, eventType, - equipmentSlot: slot - } + equipmentSlot: slot, + }, }; }; - /** * Equip action pipe definition. */ -export default [ 'equipment_change', equipmentChangeActionPipe ] as ActionPipe; +export default ['equipment_change', equipmentChangeActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-interaction.action.ts b/src/engine/action/pipe/item-interaction.action.ts index 091200200..0897851b7 100644 --- a/src/engine/action/pipe/item-interaction.action.ts +++ b/src/engine/action/pipe/item-interaction.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, numberHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; +import { numberHookFilter, questHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; import { findItem } from '@engine/config/config-handler'; import type { ItemDetails } from '@engine/config/item-config'; import type { Player } from '@engine/world/actor/player/player'; @@ -14,20 +14,18 @@ export interface ItemInteractionActionHook extends ActionHook void; - /** * Details about an item action being performed. */ @@ -48,7 +46,6 @@ export interface ItemInteractionAction { option: string; } - /** * The pipe that the game engine hands item actions off to. * @param player @@ -58,48 +55,54 @@ export interface ItemInteractionAction { * @param containerId * @param option */ -const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, widgetId: number, - containerId: number, option: string): RunnableHooks | null => { - const playerWidget = Object.values(player.interfaceState.widgetSlots).find((widget) => widget && widget.widgetId === widgetId); - - if(playerWidget && playerWidget.fakeWidget != undefined) { +const itemInteractionActionPipe = ( + player: Player, + itemId: number, + slot: number, + widgetId: number, + containerId: number, + option: string, +): RunnableHooks | null => { + const playerWidget = Object.values(player.interfaceState.widgetSlots).find(widget => widget && widget.widgetId === widgetId); + + if (playerWidget && playerWidget.fakeWidget != undefined) { widgetId = playerWidget.fakeWidget; } // Find all object action plugins that reference this location object let matchingHooks = getActionHooks('item_interaction', plugin => { - if(!questHookFilter(player, plugin)) { + if (!questHookFilter(player, plugin)) { return false; } - if(plugin.itemIds !== undefined) { - if(!numberHookFilter(plugin.itemIds, itemId)) { + if (plugin.itemIds !== undefined) { + if (!numberHookFilter(plugin.itemIds, itemId)) { return false; } } - if(plugin.widgets !== undefined) { - if(Array.isArray(plugin.widgets)) { + if (plugin.widgets !== undefined) { + if (Array.isArray(plugin.widgets)) { let found = false; - for(const widget of plugin.widgets) { - if(widget.widgetId === widgetId && widget.containerId === containerId) { + for (const widget of plugin.widgets) { + if (widget.widgetId === widgetId && widget.containerId === containerId) { found = true; break; } } - if(!found) { + if (!found) { return false; } } else { - if(plugin.widgets.widgetId !== widgetId || plugin.widgets.containerId !== containerId) { + if (plugin.widgets.widgetId !== widgetId || plugin.widgets.containerId !== containerId) { return false; } } } - if(plugin.options !== undefined) { - if(!stringHookFilter(plugin.options, option)) { + if (plugin.options !== undefined) { + if (!stringHookFilter(plugin.options, option)) { return false; } } @@ -108,19 +111,20 @@ const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { + if (matchingHooks.length === 0) { player.outgoingPackets.chatboxMessage( - `Unhandled item option: ${option} ${itemId} in slot ${slot} within widget ${widgetId}:${containerId}`); + `Unhandled item option: ${option} ${itemId} in slot ${slot} within widget ${widgetId}:${containerId}`, + ); return null; } const itemDetails = findItem(itemId); - if(!itemDetails) { + if (!itemDetails) { logger.error(`Item ${itemId} not registered on the server [item-interaction action pipe]`); return null; } @@ -134,14 +138,12 @@ const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, widgetId, containerId, itemDetails, - option - } - } - + option, + }, + }; }; - /** * Item action pipe definition. */ -export default [ 'item_interaction', itemInteractionActionPipe ] as ActionPipe; +export default ['item_interaction', itemInteractionActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-on-item.action.ts b/src/engine/action/pipe/item-on-item.action.ts index 8da47bf9b..a1b3aa69f 100644 --- a/src/engine/action/pipe/item-on-item.action.ts +++ b/src/engine/action/pipe/item-on-item.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import { questHookFilter } from '@engine/action/hook/hook-filters'; @@ -10,16 +10,14 @@ import type { Item } from '@engine/world/items/item'; */ export interface ItemOnItemActionHook extends ActionHook { // The item pairs being used. Each item can be used on the other, so item order does not matter. - items: { item1: number, item2?: number }[]; + items: { item1: number; item2?: number }[]; } - /** * The item-on-item action hook handler function to be called when the hook's conditions are met. */ export type itemOnItemActionHandler = (itemOnItemAction: ItemOnItemAction) => void; - /** * Details about an item-on-item action being performed. */ @@ -40,7 +38,6 @@ export interface ItemOnItemAction { usedWithWidgetId: number; } - /** * The pipe that the game engine hands item-on-item actions off to. * @param player @@ -51,25 +48,32 @@ export interface ItemOnItemAction { * @param usedWithSlot * @param usedWithWidgetId */ -const itemOnItemActionPipe = (player: Player, usedItem: Item, usedSlot: number, usedWidgetId: number, - usedWithItem: Item, usedWithSlot: number, usedWithWidgetId: number): RunnableHooks | null => { - if(player.busy) { +const itemOnItemActionPipe = ( + player: Player, + usedItem: Item, + usedSlot: number, + usedWidgetId: number, + usedWithItem: Item, + usedWithSlot: number, + usedWithWidgetId: number, +): RunnableHooks | null => { + if (player.busy) { return null; } // Find all item on item action plugins that match this action let matchingHooks = getActionHooks('item_on_item', plugin => { - if(questHookFilter(player, plugin)) { + if (questHookFilter(player, plugin)) { const used = usedItem.itemId; const usedWith = usedWithItem.itemId; - return (plugin.items.some(({ item1, item2 }) => { + return plugin.items.some(({ item1, item2 }) => { if (item2) { return (item1 === used && item2 === usedWith) || (item1 === usedWith && item2 === used); } return item1 === used || item1 === usedWith; - })); + }); } return false; @@ -77,27 +81,30 @@ const itemOnItemActionPipe = (player: Player, usedItem: Item, usedSlot: number, const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage( - `Unhandled item on item interaction: ${usedItem.itemId} on ${usedWithItem.itemId}`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage(`Unhandled item on item interaction: ${usedItem.itemId} on ${usedWithItem.itemId}`); return null; } return { hooks: matchingHooks, action: { - player, usedItem, usedWithItem, usedSlot, usedWithSlot, - usedWidgetId: usedWidgetId, usedWithWidgetId: usedWithWidgetId - } - } + player, + usedItem, + usedWithItem, + usedSlot, + usedWithSlot, + usedWidgetId: usedWidgetId, + usedWithWidgetId: usedWithWidgetId, + }, + }; }; - /** * Item-on-item action pipe definition. */ -export default [ 'item_on_item', itemOnItemActionPipe ] as ActionPipe; +export default ['item_on_item', itemOnItemActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-on-npc.action.ts b/src/engine/action/pipe/item-on-npc.action.ts index de6f86bef..858c95566 100644 --- a/src/engine/action/pipe/item-on-npc.action.ts +++ b/src/engine/action/pipe/item-on-npc.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, stringHookFilter, advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { advancedNumberHookFilter, questHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; import { WalkToActorPluginTask } from '@engine/action/pipe/task/walk-to-actor-plugin-task'; import type { Npc } from '@engine/world/actor/npc'; import type { Player } from '@engine/world/actor/player/player'; @@ -20,13 +20,11 @@ export interface ItemOnNpcActionHook extends ActionHook void; - /** * Details about an item-on-npc action being performed. */ @@ -45,7 +43,6 @@ export interface ItemOnNpcAction { itemContainerId: number; } - /** * The pipe that the game engine hands item-on-npc actions off to. * @param player @@ -55,23 +52,34 @@ export interface ItemOnNpcAction { * @param itemWidgetId * @param itemContainerId */ -const itemOnNpcActionPipe = (player: Player, npc: Npc, position: Position, item: Item, - itemWidgetId: number, itemContainerId: number): RunnableHooks | null => { +const itemOnNpcActionPipe = ( + player: Player, + npc: Npc, + position: Position, + item: Item, + itemWidgetId: number, + itemContainerId: number, +): RunnableHooks | null => { const morphedNpc = player.getMorphedNpcDetails(npc); // Find all item on npc action plugins that reference this npc and item - let matchingHooks = getActionHooks('item_on_npc').filter(plugin => - questHookFilter(player, plugin) && - stringHookFilter(plugin.npcs, morphedNpc?.key || npc.key) && advancedNumberHookFilter(plugin.itemIds, item.itemId)); + let matchingHooks = getActionHooks('item_on_npc').filter( + plugin => + questHookFilter(player, plugin) && + stringHookFilter(plugin.npcs, morphedNpc?.key || npc.key) && + advancedNumberHookFilter(plugin.itemIds, item.itemId), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage(`Unhandled item on npc interaction: ${ item.itemId } on ${ morphedNpc?.name || npc.name } ` + - `(id-${ morphedNpc?.gameId || npc.id }) @ ${ position.x },${ position.y },${ position.level }`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled item on npc interaction: ${item.itemId} on ${morphedNpc?.name || npc.name} ` + + `(id-${morphedNpc?.gameId || npc.id}) @ ${position.x},${position.y},${position.level}`, + ); if (morphedNpc) { player.outgoingPackets.chatboxMessage(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`); } @@ -81,11 +89,13 @@ const itemOnNpcActionPipe = (player: Player, npc: Npc, position: Position, item: const walkToPlugins = matchingHooks.filter(plugin => plugin.walkTo); if (walkToPlugins.length > 0) { - player.enqueueBaseTask(new WalkToActorPluginTask(walkToPlugins, player, 'npc', npc, { - item, - itemWidgetId, - itemContainerId - })); + player.enqueueBaseTask( + new WalkToActorPluginTask(walkToPlugins, player, 'npc', npc, { + item, + itemWidgetId, + itemContainerId, + }), + ); return null; } @@ -98,13 +108,12 @@ const itemOnNpcActionPipe = (player: Player, npc: Npc, position: Position, item: position, item, itemWidgetId, - itemContainerId - } - } + itemContainerId, + }, + }; }; - /** * Item-on-npc action pipe definition. */ -export default [ 'item_on_npc', itemOnNpcActionPipe ] as ActionPipe; +export default ['item_on_npc', itemOnNpcActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-on-object.action.ts b/src/engine/action/pipe/item-on-object.action.ts index 41e770a65..b76ab2c61 100644 --- a/src/engine/action/pipe/item-on-object.action.ts +++ b/src/engine/action/pipe/item-on-object.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { advancedNumberHookFilter, questHookFilter } from '@engine/action/hook/hook-filters'; import { WalkToObjectPluginTask } from '@engine/action/pipe/task/walk-to-object-plugin-task'; import type { Player } from '@engine/world/actor/player/player'; import type { Item } from '@engine/world/items/item'; @@ -20,13 +20,11 @@ export interface ItemOnObjectActionHook extends ActionHook void; - /** * Details about an item-on-object action being performed. */ @@ -49,7 +47,6 @@ export interface ItemOnObjectAction { cacheOriginal: boolean; } - /** * The pipe that the game engine hands item-on-object actions off to. * @param player @@ -61,41 +58,51 @@ export interface ItemOnObjectAction { * @param itemContainerId * @param cacheOriginal */ -const itemOnObjectActionPipe = (player: Player, landscapeObject: LandscapeObject, - objectConfig: ObjectConfig, position: Position, - item: Item, itemWidgetId: number, itemContainerId: number, - cacheOriginal: boolean): RunnableHooks | null => { +const itemOnObjectActionPipe = ( + player: Player, + landscapeObject: LandscapeObject, + objectConfig: ObjectConfig, + position: Position, + item: Item, + itemWidgetId: number, + itemContainerId: number, + cacheOriginal: boolean, +): RunnableHooks | null => { // Find all item on object action plugins that reference this location object - let matchingHooks = getActionHooks('item_on_object') - .filter(plugin => questHookFilter(player, plugin) && - advancedNumberHookFilter(plugin.objectIds, landscapeObject.objectId)); + let matchingHooks = getActionHooks('item_on_object').filter( + plugin => questHookFilter(player, plugin) && advancedNumberHookFilter(plugin.objectIds, landscapeObject.objectId), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } // Find all item on object action plugins that reference this item - if(matchingHooks.length !== 0) { + if (matchingHooks.length !== 0) { matchingHooks = matchingHooks.filter(plugin => advancedNumberHookFilter(plugin.itemIds, item.itemId)); } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage(`Unhandled item on object interaction: ${ item.itemId } on ${ objectConfig.name } ` + - `(id-${ landscapeObject.objectId }) @ ${ position.x },${ position.y },${ position.level }`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled item on object interaction: ${item.itemId} on ${objectConfig.name} ` + + `(id-${landscapeObject.objectId}) @ ${position.x},${position.y},${position.level}`, + ); return null; } const walkToPlugins = matchingHooks.filter(plugin => plugin.walkTo); if (walkToPlugins.length > 0) { - player.enqueueBaseTask(new WalkToObjectPluginTask(walkToPlugins, player, landscapeObject, { - objectConfig, - item, - itemWidgetId, - itemContainerId, - cacheOriginal - })); + player.enqueueBaseTask( + new WalkToObjectPluginTask(walkToPlugins, player, landscapeObject, { + objectConfig, + item, + itemWidgetId, + itemContainerId, + cacheOriginal, + }), + ); return null; } @@ -110,13 +117,12 @@ const itemOnObjectActionPipe = (player: Player, landscapeObject: LandscapeObject item, itemWidgetId, itemContainerId, - cacheOriginal - } - } + cacheOriginal, + }, + }; }; - /** * Item-on-object action pipe definition. */ -export default [ 'item_on_object', itemOnObjectActionPipe ] as ActionPipe; +export default ['item_on_object', itemOnObjectActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-on-player.action.ts b/src/engine/action/pipe/item-on-player.action.ts index ff2bf989d..e47eeb65d 100644 --- a/src/engine/action/pipe/item-on-player.action.ts +++ b/src/engine/action/pipe/item-on-player.action.ts @@ -1,7 +1,7 @@ import type { ActionPipe } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { advancedNumberHookFilter, questHookFilter } from '@engine/action/hook/hook-filters'; import { WalkToActorPluginTask } from '@engine/action/pipe/task/walk-to-actor-plugin-task'; import type { Player } from '@engine/world/actor/player/player'; import type { Item } from '@engine/world/items/item'; @@ -17,13 +17,11 @@ export interface ItemOnPlayerActionHook extends ActionHook void; - /** * Details about an item-on-player action being performed. */ @@ -42,7 +40,6 @@ export interface ItemOnPlayerAction { itemContainerId: number; } - // @TODO update /** * The pipe that the game engine hands item-on-player actions off to. @@ -53,24 +50,32 @@ export interface ItemOnPlayerAction { * @param itemWidgetId * @param itemContainerId */ -const itemOnPlayerActionPipe = (player: Player, otherPlayer: Player, position: Position, item: Item, - itemWidgetId: number, itemContainerId: number): void => { - if(player.busy) { +const itemOnPlayerActionPipe = ( + player: Player, + otherPlayer: Player, + position: Position, + item: Item, + itemWidgetId: number, + itemContainerId: number, +): void => { + if (player.busy) { return; } // Find all item on player action plugins that reference this item - let interactionActions = getActionHooks('item_on_player').filter(plugin => - questHookFilter(player, plugin) && advancedNumberHookFilter(plugin.itemIds, item.itemId)); + let interactionActions = getActionHooks('item_on_player').filter( + plugin => questHookFilter(player, plugin) && advancedNumberHookFilter(plugin.itemIds, item.itemId), + ); const questActions = interactionActions.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { interactionActions = questActions; } - if(interactionActions.length === 0) { - player.outgoingPackets.chatboxMessage(`Unhandled item on player interaction: ${ item.itemId } ` + - `@ ${ position.x },${ position.y },${ position.level }`); + if (interactionActions.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled item on player interaction: ${item.itemId} ` + `@ ${position.x},${position.y},${position.level}`, + ); return; } @@ -79,30 +84,31 @@ const itemOnPlayerActionPipe = (player: Player, otherPlayer: Player, position: P const immediateHooks = interactionActions.filter(plugin => !plugin.walkTo); if (walkToPlugins.length > 0) { - player.enqueueBaseTask(new WalkToActorPluginTask(walkToPlugins, player, 'otherPlayer', otherPlayer, { - item, - itemWidgetId, - itemContainerId - })); + player.enqueueBaseTask( + new WalkToActorPluginTask(walkToPlugins, player, 'otherPlayer', otherPlayer, { + item, + itemWidgetId, + itemContainerId, + }), + ); return; } // Immediately run any non-walk-to plugins - for(const actionHook of immediateHooks) { + for (const actionHook of immediateHooks) { actionHook.handler({ player, otherPlayer, position, item, itemWidgetId, - itemContainerId + itemContainerId, }); } }; - /** * Item-on-player action pipe definition. */ -export default [ 'item_on_player', itemOnPlayerActionPipe ] as ActionPipe; +export default ['item_on_player', itemOnPlayerActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-on-world-item.action.ts b/src/engine/action/pipe/item-on-world-item.action.ts index e3f08b3c4..1ad90c028 100644 --- a/src/engine/action/pipe/item-on-world-item.action.ts +++ b/src/engine/action/pipe/item-on-world-item.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import { questHookFilter } from '@engine/action/hook/hook-filters'; @@ -15,16 +15,14 @@ export interface ItemOnWorldItemActionHook extends ActionHook void; - /** * Details about an item-on-world-item action being performed. * @@ -73,25 +71,28 @@ export interface ItemOnWorldItemAction { */ const itemOnWorldItemActionPipe = ( player: Player, - usedItem: Item, usedWithItem: WorldItem, - usedWidgetId: number, usedContainerId: number, usedSlot: number + usedItem: Item, + usedWithItem: WorldItem, + usedWidgetId: number, + usedContainerId: number, + usedSlot: number, ): RunnableHooks | null => { - if(player.busy) { + if (player.busy) { return null; } // Find all item on item action plugins that match this action let matchingHooks = getActionHooks('item_on_world_item', plugin => { - if(questHookFilter(player, plugin)) { + if (questHookFilter(player, plugin)) { const used = usedItem.itemId; const usedWith = usedWithItem.itemId; - return (plugin.items.some(({ item, worldItem }) => { + return plugin.items.some(({ item, worldItem }) => { const itemMatch = item === undefined || item === used; const worldItemMatch = worldItem === undefined || worldItem === usedWith; return itemMatch && worldItemMatch; - })); + }); } return false; @@ -99,13 +100,12 @@ const itemOnWorldItemActionPipe = ( const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage( - `Unhandled item on world item interaction: ${usedItem.itemId} on ${usedWithItem.itemId}`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage(`Unhandled item on world item interaction: ${usedItem.itemId} on ${usedWithItem.itemId}`); return null; } @@ -113,14 +113,16 @@ const itemOnWorldItemActionPipe = ( hooks: matchingHooks, action: { player, - usedItem, usedWithItem, - usedWidgetId, usedContainerId, usedSlot - } - } + usedItem, + usedWithItem, + usedWidgetId, + usedContainerId, + usedSlot, + }, + }; }; - /** * Item-on-world-item action pipe definition. */ -export default [ 'item_on_world_item', itemOnWorldItemActionPipe ] as ActionPipe; +export default ['item_on_world_item', itemOnWorldItemActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/item-swap.action.ts b/src/engine/action/pipe/item-swap.action.ts index c7194a0f4..3b8473d62 100644 --- a/src/engine/action/pipe/item-swap.action.ts +++ b/src/engine/action/pipe/item-swap.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import { numberHookFilter } from '@engine/action/hook/hook-filters'; @@ -12,13 +12,11 @@ export interface ItemSwapActionHook extends ActionHook void; - /** * Details about a swap items action being performed. */ @@ -35,7 +33,6 @@ export interface ItemSwapAction { toSlot: number; } - /** * The pipe that the game engine hands swap items actions off to. * @param player @@ -43,16 +40,20 @@ export interface ItemSwapAction { * @param toSlot * @param widget */ -const itemSwapActionPipe = (player: Player, fromSlot: number, toSlot: number, - widget: { widgetId: number, containerId: number }): RunnableHooks | null => { - const matchingHooks = getActionHooks('item_swap') - .filter(plugin => ( - (plugin.widgetId || plugin.widgetIds) - && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) - )); +const itemSwapActionPipe = ( + player: Player, + fromSlot: number, + toSlot: number, + widget: { widgetId: number; containerId: number }, +): RunnableHooks | null => { + const matchingHooks = getActionHooks('item_swap').filter( + plugin => (plugin.widgetId || plugin.widgetIds) && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId), + ); - if(!matchingHooks || matchingHooks.length === 0) { - player.sendMessage(`Unhandled Swap Items action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`); + if (!matchingHooks || matchingHooks.length === 0) { + player.sendMessage( + `Unhandled Swap Items action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`, + ); return null; } @@ -63,13 +64,12 @@ const itemSwapActionPipe = (player: Player, fromSlot: number, toSlot: number, widgetId: widget.widgetId, containerId: widget.containerId, fromSlot, - toSlot - } + toSlot, + }, }; }; - /** * Swap items action pipe definition. */ -export default [ 'item_swap', itemSwapActionPipe ] as ActionPipe; +export default ['item_swap', itemSwapActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/magic-on-npc.action.ts b/src/engine/action/pipe/magic-on-npc.action.ts index 034e6cc0a..ad6360e1f 100644 --- a/src/engine/action/pipe/magic-on-npc.action.ts +++ b/src/engine/action/pipe/magic-on-npc.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import type { Npc } from '@engine/world/actor/npc'; @@ -18,13 +18,11 @@ export interface MagicOnNPCActionHook extends ActionHook void | Promise; - /** * Details about a button action being performed. */ @@ -39,7 +37,6 @@ export interface MagicOnNPCAction { buttonId: number; } - /** * The pipe that the game engine hands button actions off to. * @param npc @@ -47,7 +44,7 @@ export interface MagicOnNPCAction { * @param widgetId * @param buttonId */ -const magicOnNpcActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { +const magicOnNpcActionPipe = (npc: Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { //console.info(`pew pew you use magic on ${npc.name}!`); // Find all object action plugins that reference this location object @@ -59,15 +56,12 @@ const magicOnNpcActionPipe = (npc:Npc, player: Player, widgetId: number, buttonI npc, player, widgetId, - buttonId - } - } - - + buttonId, + }, + }; }; - /** * Button action pipe definition. */ -export default [ 'magic_on_npc', magicOnNpcActionPipe ] as ActionPipe; +export default ['magic_on_npc', magicOnNpcActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/move-item.action.ts b/src/engine/action/pipe/move-item.action.ts index e643a58f7..555298b47 100644 --- a/src/engine/action/pipe/move-item.action.ts +++ b/src/engine/action/pipe/move-item.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import { numberHookFilter } from '@engine/action/hook/hook-filters'; @@ -12,13 +12,11 @@ export interface MoveItemActionHook extends ActionHook void; - /** * Details about a move item action being performed. */ @@ -35,7 +33,6 @@ export interface MoveItemAction { toSlot: number; } - /** * The pipe that the game engine hands move item actions off to. * @param player @@ -43,16 +40,20 @@ export interface MoveItemAction { * @param toSlot * @param widget */ -const moveItemActionPipe = (player: Player, fromSlot: number, toSlot: number, - widget: { widgetId: number, containerId: number }): RunnableHooks | null => { - const matchingHooks = getActionHooks('move_item') - .filter(plugin => ( - (plugin.widgetId || plugin.widgetIds) - && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) - )); +const moveItemActionPipe = ( + player: Player, + fromSlot: number, + toSlot: number, + widget: { widgetId: number; containerId: number }, +): RunnableHooks | null => { + const matchingHooks = getActionHooks('move_item').filter( + plugin => (plugin.widgetId || plugin.widgetIds) && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId), + ); - if(!matchingHooks || matchingHooks.length === 0) { - player.sendMessage(`Unhandled Move Item action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`); + if (!matchingHooks || matchingHooks.length === 0) { + player.sendMessage( + `Unhandled Move Item action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`, + ); return null; } @@ -63,13 +64,12 @@ const moveItemActionPipe = (player: Player, fromSlot: number, toSlot: number, widgetId: widget.widgetId, containerId: widget.containerId, fromSlot, - toSlot - } + toSlot, + }, }; }; - /** * Move item action pipe definition. */ -export default [ 'move_item', moveItemActionPipe ] as ActionPipe; +export default ['move_item', moveItemActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/npc-init.action.ts b/src/engine/action/pipe/npc-init.action.ts index 54e89fde3..44ca1f874 100644 --- a/src/engine/action/pipe/npc-init.action.ts +++ b/src/engine/action/pipe/npc-init.action.ts @@ -12,13 +12,11 @@ export interface NpcInitActionHook extends ActionHook void; - /** * Details about an npc init action being performed. */ @@ -27,14 +25,14 @@ export interface NpcInitAction { npc: Npc; } - /** * The pipe that the game engine hands npc init actions off to. * @param npc */ const npcInitActionPipe = ({ npc }: NpcInitAction): void => { - const actionHooks = getActionHooks('npc_init') - .filter(plugin => (!plugin.npcs || stringHookFilter(plugin.npcs, npc.key))); + const actionHooks = getActionHooks('npc_init').filter( + plugin => !plugin.npcs || stringHookFilter(plugin.npcs, npc.key), + ); actionHooks.forEach(actionHook => { if (!actionHook.handler) { return; @@ -44,8 +42,7 @@ const npcInitActionPipe = ({ npc }: NpcInitAction): void => { }); }; - /** * Npc init action pipe definition. */ -export default [ 'npc_init', npcInitActionPipe ] as ActionPipe; +export default ['npc_init', npcInitActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/npc-interaction.action.ts b/src/engine/action/pipe/npc-interaction.action.ts index 31c330e59..00c8917dd 100644 --- a/src/engine/action/pipe/npc-interaction.action.ts +++ b/src/engine/action/pipe/npc-interaction.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import { questHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; @@ -19,13 +19,11 @@ export interface NpcInteractionActionHook extends ActionHook void; - /** * Details about an npc action being performed. */ @@ -40,7 +38,6 @@ export interface NpcInteractionAction { option: string; } - /** * The pipe that the game engine hands npc actions off to. * @param player @@ -48,27 +45,35 @@ export interface NpcInteractionAction { * @param position * @param option */ -const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position, option: string): RunnableHooks | null => { - if(player.busy) { +const npcInteractionActionPipe = ( + player: Player, + npc: Npc, + position: Position, + option: string, +): RunnableHooks | null => { + if (player.busy) { return null; } const morphedNpc = player.getMorphedNpcDetails(npc); // Find all NPC action plugins that reference this NPC - let matchingHooks = getActionHooks('npc_interaction') - .filter(plugin => questHookFilter(player, plugin) && + let matchingHooks = getActionHooks('npc_interaction').filter( + plugin => + questHookFilter(player, plugin) && (!plugin.npcs || stringHookFilter(plugin.npcs, morphedNpc?.key || npc.key)) && - (!plugin.options || stringHookFilter(plugin.options, option))); + (!plugin.options || stringHookFilter(plugin.options, option)), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage(`Unhandled NPC interaction: ${option} ${morphedNpc?.key || npc.key} (id-${morphedNpc?.gameId || npc.id}) @ ${position.x},${position.y},${position.level}`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled NPC interaction: ${option} ${morphedNpc?.key || npc.key} (id-${morphedNpc?.gameId || npc.id}) @ ${position.x},${position.y},${position.level}`, + ); if (morphedNpc) { player.outgoingPackets.chatboxMessage(`Note: (id-${morphedNpc.gameId}) is a morphed NPC. The parent NPC is (id-${npc.id}).`); } @@ -87,13 +92,15 @@ const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position, return { hooks: matchingHooks, action: { - player, npc, position, option - } - } + player, + npc, + position, + option, + }, + }; }; - /** * Npc action pipe definition. */ -export default [ 'npc_interaction', npcInteractionActionPipe ] as ActionPipe; +export default ['npc_interaction', npcInteractionActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/object-interaction.action.ts b/src/engine/action/pipe/object-interaction.action.ts index ec7576e61..8d9aa6d4c 100644 --- a/src/engine/action/pipe/object-interaction.action.ts +++ b/src/engine/action/pipe/object-interaction.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { advancedNumberHookFilter, questHookFilter } from '@engine/action/hook/hook-filters'; import { WalkToObjectPluginTask } from '@engine/action/pipe/task/walk-to-object-plugin-task'; import type { Player } from '@engine/world/actor/player/player'; import type { Position } from '@engine/world/position'; @@ -19,13 +19,11 @@ export interface ObjectInteractionActionHook extends ActionHook void; - /** * Details about an object action being performed. */ @@ -44,7 +42,6 @@ export interface ObjectInteractionAction { option: string; } - /** * The pipe that the game engine hands object actions off to. * @param player @@ -54,25 +51,34 @@ export interface ObjectInteractionAction { * @param option * @param cacheOriginal */ -const objectInteractionActionPipe = (player: Player, landscapeObject: LandscapeObject, objectConfig: ObjectConfig, - position: Position, option: string, cacheOriginal: boolean): RunnableHooks | null => { - if(player.metadata.blockObjectInteractions) { +const objectInteractionActionPipe = ( + player: Player, + landscapeObject: LandscapeObject, + objectConfig: ObjectConfig, + position: Position, + option: string, + cacheOriginal: boolean, +): RunnableHooks | null => { + if (player.metadata.blockObjectInteractions) { return null; } // Find all object action plugins that reference this location object - let matchingHooks = getActionHooks('object_interaction') - .filter(plugin => questHookFilter(player, plugin) && - advancedNumberHookFilter(plugin.objectIds, landscapeObject.objectId, plugin.options, option)); + let matchingHooks = getActionHooks('object_interaction').filter( + plugin => + questHookFilter(player, plugin) && advancedNumberHookFilter(plugin.objectIds, landscapeObject.objectId, plugin.options, option), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { - player.outgoingPackets.chatboxMessage(`Unhandled object interaction: ${option} ${objectConfig.name} ` + - `(id-${landscapeObject.objectId}) @ ${position.x},${position.y},${position.level}`); + if (matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled object interaction: ${option} ${objectConfig.name} ` + + `(id-${landscapeObject.objectId}) @ ${position.x},${position.y},${position.level}`, + ); return null; } @@ -92,13 +98,12 @@ const objectInteractionActionPipe = (player: Player, landscapeObject: LandscapeO objectConfig, option, position, - cacheOriginal - } - } + cacheOriginal, + }, + }; }; - /** * Object action pipe definition. */ -export default [ 'object_interaction', objectInteractionActionPipe ] as ActionPipe; +export default ['object_interaction', objectInteractionActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/player-command.action.ts b/src/engine/action/pipe/player-command.action.ts index a382993c6..e181f58fd 100644 --- a/src/engine/action/pipe/player-command.action.ts +++ b/src/engine/action/pipe/player-command.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { reloadContentCommands, reloadContent } from '@engine/plugins/reload-content'; +import { reloadContent, reloadContentCommands } from '@engine/plugins/reload-content'; import type { Player } from '@engine/world/actor/player/player'; import { logger } from '@runejs/common'; @@ -19,13 +19,11 @@ export interface PlayerCommandActionHook extends ActionHook void; - /** * Details about a player command action being performed. */ @@ -40,7 +38,6 @@ export interface PlayerCommandAction { args: { [key: string]: number | string }; } - /** * The pipe that the game engine hands player command actions off to. * @param player @@ -48,8 +45,12 @@ export interface PlayerCommandAction { * @param isConsole * @param inputArgs */ -const playerCommandActionPipe = (player: Player, command: string, isConsole: boolean, - inputArgs: string[]): RunnableHooks | null => { +const playerCommandActionPipe = ( + player: Player, + command: string, + isConsole: boolean, + inputArgs: string[], +): RunnableHooks | null => { command = command.toLowerCase(); // Reload game content @@ -62,17 +63,17 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo const plugins = getActionHooks('player_command').filter(actionHook => { let valid: boolean; - if(Array.isArray(actionHook.commands)) { + if (Array.isArray(actionHook.commands)) { valid = actionHook.commands.indexOf(command) !== -1; } else { valid = actionHook.commands === command; } - if(!valid) { + if (!valid) { return false; } - if(actionHook.args) { + if (actionHook.args) { const args = actionHook.args; let syntaxError = `Syntax error. Try ::${command}`; @@ -81,32 +82,31 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo }); const requiredArgLength = actionHook.args.filter(arg => arg.defaultValue === undefined).length; - if(requiredArgLength > inputArgs.length) { + if (requiredArgLength > inputArgs.length) { player.sendLogMessage(syntaxError, isConsole); return; } - - for(let i = 0; i < actionHook.args.length; i++) { + for (let i = 0; i < actionHook.args.length; i++) { let argValue: string | number | null = inputArgs[i] || null; const pluginArg = actionHook.args[i]; - if(argValue === null || argValue === undefined) { - if(pluginArg.defaultValue === undefined) { + if (argValue === null || argValue === undefined) { + if (pluginArg.defaultValue === undefined) { player.sendLogMessage(syntaxError, isConsole); return; } else { argValue = pluginArg.defaultValue; } } else { - if(pluginArg.type === 'number') { + if (pluginArg.type === 'number') { argValue = parseInt(argValue); - if(isNaN(argValue)) { + if (isNaN(argValue)) { player.sendLogMessage(syntaxError, isConsole); return; } - } else if(pluginArg.type === 'string') { - if(!argValue || argValue.trim() === '') { + } else if (pluginArg.type === 'string') { + if (!argValue || argValue.trim() === '') { player.sendLogMessage(syntaxError, isConsole); return; } @@ -120,8 +120,8 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo return true; }); - if(plugins.length === 0) { - player.sendLogMessage(`Unhandled command: ${ command }`, isConsole); + if (plugins.length === 0) { + player.sendLogMessage(`Unhandled command: ${command}`, isConsole); return null; } @@ -131,13 +131,12 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo player, command, isConsole, - args: actionArgs - } - } + args: actionArgs, + }, + }; }; - /** * Player command action pipe definition. */ -export default [ 'player_command', playerCommandActionPipe ] as ActionPipe; +export default ['player_command', playerCommandActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/player-init.action.ts b/src/engine/action/pipe/player-init.action.ts index 5496bd855..3c3b07964 100644 --- a/src/engine/action/pipe/player-init.action.ts +++ b/src/engine/action/pipe/player-init.action.ts @@ -8,13 +8,11 @@ import type { Player } from '@engine/world/actor/player/player'; */ export type PlayerInitActionHook = ActionHook; - /** * The player init action hook handler function to be called when the hook's conditions are met. */ export type playerInitActionHandler = (playerInitAction: PlayerInitAction) => void; - /** * Details about a player init action being performed. */ @@ -23,7 +21,6 @@ export interface PlayerInitAction { player: Player; } - /** * The pipe that the game engine hands player init actions off to. * @param player @@ -39,8 +36,7 @@ const playerInitActionPipe = ({ player }: PlayerInitAction): void => { }); }; - /** * Player init action pipe definition. */ -export default [ 'player_init', playerInitActionPipe ] as ActionPipe; +export default ['player_init', playerInitActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/player-interaction.action.ts b/src/engine/action/pipe/player-interaction.action.ts index 884803df8..7eb07e217 100644 --- a/src/engine/action/pipe/player-interaction.action.ts +++ b/src/engine/action/pipe/player-interaction.action.ts @@ -16,13 +16,11 @@ export interface PlayerInteractionActionHook extends ActionHook void; - /** * Details about a player action being performed. */ @@ -35,7 +33,6 @@ export interface PlayerInteractionAction { position: Position; } - /** * The pipe that the game engine hands player actions off to. * @param player @@ -43,18 +40,23 @@ export interface PlayerInteractionAction { * @param position * @param option */ -const playerInteractionActionPipe = (player: Player, otherPlayer: Player, position: Position, - option: string): RunnableHooks | null => { +const playerInteractionActionPipe = ( + player: Player, + otherPlayer: Player, + position: Position, + option: string, +): RunnableHooks | null => { // Find all player action plugins that reference this option - let matchingHooks = getActionHooks('player_interaction') - .filter(plugin => questHookFilter(player, plugin) && stringHookFilter(plugin.options, option)); + let matchingHooks = getActionHooks('player_interaction').filter( + plugin => questHookFilter(player, plugin) && stringHookFilter(plugin.options, option), + ); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { + if (matchingHooks.length === 0) { player.sendMessage(`Unhandled Player interaction: ${option} @ ${position.x},${position.y},${position.level}`); return null; } @@ -72,13 +74,12 @@ const playerInteractionActionPipe = (player: Player, otherPlayer: Player, positi action: { player, otherPlayer, - position - } - } + position, + }, + }; }; - /** * Player action pipe definition. */ -export default [ 'player_interaction', playerInteractionActionPipe ]; +export default ['player_interaction', playerInteractionActionPipe]; diff --git a/src/engine/action/pipe/prayer.action.ts b/src/engine/action/pipe/prayer.action.ts index ac13b9831..7eb004f32 100644 --- a/src/engine/action/pipe/prayer.action.ts +++ b/src/engine/action/pipe/prayer.action.ts @@ -1,4 +1,4 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; import type { Npc } from '@engine/world/actor/npc'; @@ -18,13 +18,11 @@ export interface PrayerActionHook extends ActionHook void | Promise; - /** * Details about a button action being performed. */ @@ -39,7 +37,6 @@ export interface PrayerAction { buttonId: number; } - /** * The pipe that the game engine hands button actions off to. * @param npc @@ -47,7 +44,7 @@ export interface PrayerAction { * @param widgetId * @param buttonId */ -const prayerActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { +const prayerActionPipe = (npc: Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { console.info(`You used prayer`); // Find all object action plugins that reference this location object @@ -59,15 +56,12 @@ const prayerActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: n npc, player, widgetId, - buttonId - } - } - - + buttonId, + }, + }; }; - /** * Button action pipe definition. */ -export default [ 'prayer', prayerActionPipe ] as ActionPipe; +export default ['prayer', prayerActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/region-change.action.ts b/src/engine/action/pipe/region-change.action.ts index 347263695..352f458a8 100644 --- a/src/engine/action/pipe/region-change.action.ts +++ b/src/engine/action/pipe/region-change.action.ts @@ -18,13 +18,11 @@ export interface RegionChangeActionHook extends ActionHook void; - /** * Details about a player region change action being performed. */ @@ -53,7 +51,6 @@ export interface RegionChangeAction { regionTypes: RegionType[]; } - /** * Creates a RegionChangeAction object from the given inputs. * @@ -65,44 +62,49 @@ export interface RegionChangeAction { * @param currentPosition The player's current position. * @param teleporting Whether or not the player is teleporting; defaults to false. */ -export const regionChangeActionFactory = (player: Player, - originalPosition: Position, currentPosition: Position, - teleporting: boolean = false): RegionChangeAction | null => { +export const regionChangeActionFactory = ( + player: Player, + originalPosition: Position, + currentPosition: Position, + teleporting: boolean = false, +): RegionChangeAction | null => { const regionTypes: RegionType[] = []; const originalMapRegionId: number = ((originalPosition.x >> 6) << 8) + (originalPosition.y >> 6); const currentMapRegionId: number = ((currentPosition.x >> 6) << 8) + (currentPosition.y >> 6); const originalChunkCoords: Coords = { x: originalPosition.chunkX, y: originalPosition.chunkY, - level: originalPosition.level + level: originalPosition.level, }; const currentChunkCoords: Coords = { x: currentPosition.chunkX, y: currentPosition.chunkY, - level: currentPosition.level + level: currentPosition.level, }; - if(originalMapRegionId !== currentMapRegionId) { + if (originalMapRegionId !== currentMapRegionId) { regionTypes.push('region'); } - if(!Coords.equals(originalChunkCoords, currentChunkCoords)) { + if (!Coords.equals(originalChunkCoords, currentChunkCoords)) { regionTypes.push('chunk'); } - if(regionTypes.length === 0) { + if (regionTypes.length === 0) { return null; } return { - player, regionTypes, teleporting, + player, + regionTypes, + teleporting, originalPosition, originalChunkCoords, originalMapRegionCoords: { x: originalPosition.x >> 6, y: originalPosition.y >> 6, - level: originalPosition.level + level: originalPosition.level, }, originalMapRegionId, @@ -111,68 +113,69 @@ export const regionChangeActionFactory = (player: Player, currentMapRegionCoords: { x: currentPosition.x >> 6, y: currentPosition.y >> 6, - level: currentPosition.level + level: currentPosition.level, }, - currentMapRegionId + currentMapRegionId, }; }; - /** * The pipe that the game engine hands player region change actions off to. * @param actionData */ const regionChangeActionPipe = (actionData: RegionChangeAction): void => { - if(!actionData) { + if (!actionData) { return; } const { regionTypes } = actionData; - if(!regionTypes || regionTypes.length === 0) { + if (!regionTypes || regionTypes.length === 0) { return; } // Find all action hooks that match the provided input - const actionList = getActionHooks('region_change')?.filter(actionHook => { - if(actionHook.teleporting && !actionData.teleporting) { - return false; - } - - if(actionHook.regionType) { - return regionTypes.indexOf(actionHook.regionType) !== -1; - } else if(actionHook.regionTypes && actionHook.regionTypes.length !== 0) { - let valid = false; - for(const type of actionHook.regionTypes) { - if(regionTypes.indexOf(type) !== -1) { - valid = true; - break; - } + const actionList = + getActionHooks('region_change')?.filter(actionHook => { + if (actionHook.teleporting && !actionData.teleporting) { + return false; } - return valid; - } + if (actionHook.regionType) { + return regionTypes.indexOf(actionHook.regionType) !== -1; + } else if (actionHook.regionTypes && actionHook.regionTypes.length !== 0) { + let valid = false; + for (const type of actionHook.regionTypes) { + if (regionTypes.indexOf(type) !== -1) { + valid = true; + break; + } + } - return false; - }) || null; + return valid; + } + + return false; + }) || null; - if(!actionList || actionList.length === 0) { + if (!actionList || actionList.length === 0) { // No matching actions found return; } - actionList.forEach(async actionHook => - new Promise(resolve => { - if (actionHook && actionHook.handler) { - actionHook.handler(actionData); - } + actionList.forEach( + async actionHook => + new Promise(resolve => { + if (actionHook && actionHook.handler) { + actionHook.handler(actionData); + } - resolve(); - })); + resolve(); + }), + ); }; - /** * Player region change action pipe definition. */ -export default [ 'region_change', regionChangeActionPipe ] as ActionPipe; +export default ['region_change', regionChangeActionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/spawned-item-interaction.action.ts b/src/engine/action/pipe/spawned-item-interaction.action.ts index c8c1b3e5c..bbda74083 100644 --- a/src/engine/action/pipe/spawned-item-interaction.action.ts +++ b/src/engine/action/pipe/spawned-item-interaction.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, numberHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; +import { numberHookFilter, questHookFilter, stringHookFilter } from '@engine/action/hook/hook-filters'; import { WalkToItemPluginTask } from '@engine/action/pipe/task/walk-to-item-plugin-task'; import { findItem } from '@engine/config/config-handler'; import type { ItemDetails } from '@engine/config/item-config'; @@ -21,13 +21,11 @@ export interface SpawnedItemInteractionHook extends ActionHook void; - /** * Details about a world item action being performed. */ @@ -42,27 +40,30 @@ export interface SpawnedItemInteractionAction { // TODO (jkm) add "option" to the action } - /** * The pipe that the game engine hands world item actions off to. * @param player * @param worldItem * @param option */ -const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option: string): RunnableHooks | null => { +const spawnedItemInteractionPipe = ( + player: Player, + worldItem: WorldItem, + option: string, +): RunnableHooks | null => { // Find all world item action plugins that reference this world item let matchingHooks = getActionHooks('spawned_item_interaction').filter(plugin => { - if(!questHookFilter(player, plugin)) { + if (!questHookFilter(player, plugin)) { return false; } - if(plugin.itemIds !== undefined) { - if(!numberHookFilter(plugin.itemIds, worldItem.itemId)) { + if (plugin.itemIds !== undefined) { + if (!numberHookFilter(plugin.itemIds, worldItem.itemId)) { return false; } } - if(!stringHookFilter(plugin.options, option)) { + if (!stringHookFilter(plugin.options, option)) { return false; } @@ -71,18 +72,18 @@ const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { + if (matchingHooks.length === 0) { player.outgoingPackets.chatboxMessage(`Unhandled world item interaction: ${option} ${worldItem.itemId}`); return null; } const itemDetails = findItem(worldItem.itemId); - if(!itemDetails) { + if (!itemDetails) { logger.error(`Item ${worldItem.itemId} not registered on the server [spawned-item-interaction action pipe]`); return null; } @@ -100,13 +101,12 @@ const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option action: { player, worldItem, - itemDetails - } - } + itemDetails, + }, + }; }; - /** * World item action pipe definition. */ -export default [ 'spawned_item_interaction', spawnedItemInteractionPipe ] as ActionPipe; +export default ['spawned_item_interaction', spawnedItemInteractionPipe] as ActionPipe; diff --git a/src/engine/action/pipe/task/queueable-task.ts b/src/engine/action/pipe/task/queueable-task.ts index 59d12550f..a5667285b 100644 --- a/src/engine/action/pipe/task/queueable-task.ts +++ b/src/engine/action/pipe/task/queueable-task.ts @@ -1,10 +1,10 @@ -import type { ObjectInteractionAction } from '../object-interaction.action'; -import type { ItemOnObjectAction } from '../item-on-object.action'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { ActorTask } from '@engine/task/impl/actor-task'; -import type { Player } from '@engine/world/actor/player/player'; -import type { Actor } from '@engine/world/actor/actor'; import type { Task } from '@engine/task/task'; +import type { Actor } from '@engine/world/actor/actor'; +import type { Player } from '@engine/world/actor/player/player'; +import type { ItemOnObjectAction } from '../item-on-object.action'; +import type { ObjectInteractionAction } from '../object-interaction.action'; /** * The result of running a callback function will be recorded here so that the @@ -37,8 +37,8 @@ type ObjectActionData = Omit extends ActorTask { + */ +export class QueueableTask extends ActorTask { /** * The plugins to execute on each tick. These will not get called if the * `callback` indicates a halting condition. @@ -59,10 +59,14 @@ export class QueueableTask extends ActorTask QueueableTaskEval; - constructor(plugins: ObjectActionHook[], actor: Player | Actor, callback: () => QueueableTaskEval, task: Task | null, data: ObjectActionData | null) { - super( - actor, - ); + constructor( + plugins: ObjectActionHook[], + actor: Player | Actor, + callback: () => QueueableTaskEval, + task: Task | null, + data: ObjectActionData | null, + ) { + super(actor); this.plugins = plugins; this.data = data; @@ -78,13 +82,14 @@ export class QueueableTask extends ActorTask extends ActorTask = Omit; /** -* This is a task to migrate old `walkTo` item interaction actions to the new task system. -* -* This is a first-pass implementation to allow for removal of the old action system. -* It will be refactored in future to be more well suited to our plugin system. -*/ -export class WalkToActorPluginTask extends ActorActorInteractionTask { + * This is a task to migrate old `walkTo` item interaction actions to the new task system. + * + * This is a first-pass implementation to allow for removal of the old action system. + * It will be refactored in future to be more well suited to our plugin system. + */ +export class WalkToActorPluginTask< + TAction extends ActorAction, + TActorKey extends ActorKey, + TOtherActor extends Actor, +> extends ActorActorInteractionTask { /** * The plugins to execute when the player arrives at the object. */ @@ -40,11 +44,14 @@ export class WalkToActorPluginTask[], player: Player, actorKey: TActorKey, other: TOtherActor, data: ActorActionData) { - super( - player, - other, - ); + constructor( + plugins: ActorActionHook[], + player: Player, + actorKey: TActorKey, + other: TOtherActor, + data: ActorActionData, + ) { + super(player, other); this.plugins = plugins; this.data = data; @@ -75,7 +82,7 @@ export class WalkToActorPluginTask { /** * The plugins to execute when the player arrives at the item. @@ -22,10 +22,7 @@ export class WalkToItemPluginTask extends ActorWorldItemInteractionTask private itemDetails: ItemDetails; constructor(plugins: SpawnedItemInteractionHook[], player: Player, worldItem: WorldItem, itemDetails: ItemDetails) { - super( - player, - worldItem - ); + super(player, worldItem); this.plugins = plugins; this.itemDetails = itemDetails; @@ -53,7 +50,7 @@ export class WalkToItemPluginTask extends ActorWorldItemInteractionTask plugin.handler({ player: this.actor, worldItem: worldItem, - itemDetails: this.itemDetails + itemDetails: this.itemDetails, }); }); diff --git a/src/engine/action/pipe/task/walk-to-object-plugin-task.ts b/src/engine/action/pipe/task/walk-to-object-plugin-task.ts index 31ddfd505..0325b90d4 100644 --- a/src/engine/action/pipe/task/walk-to-object-plugin-task.ts +++ b/src/engine/action/pipe/task/walk-to-object-plugin-task.ts @@ -21,11 +21,11 @@ type ObjectActionHook = ActionHook = Omit; /** -* This is a task to migrate old `walkTo` item interaction actions to the new task system. -* -* This is a first-pass implementation to allow for removal of the old action system. -* It will be refactored in future to be more well suited to our plugin system. -*/ + * This is a task to migrate old `walkTo` item interaction actions to the new task system. + * + * This is a first-pass implementation to allow for removal of the old action system. + * It will be refactored in future to be more well suited to our plugin system. + */ export class WalkToObjectPluginTask extends ActorLandscapeObjectInteractionTask { /** * The plugins to execute when the player arrives at the object. @@ -72,7 +72,7 @@ export class WalkToObjectPluginTask extends ActorL player: this.actor, object: landscapeObject, position: landscapeObjectPosition, - ...this.data + ...this.data, } as TAction; plugin.handler(action); diff --git a/src/engine/action/pipe/widget-interaction.action.ts b/src/engine/action/pipe/widget-interaction.action.ts index 7006c3d93..b77d106c3 100644 --- a/src/engine/action/pipe/widget-interaction.action.ts +++ b/src/engine/action/pipe/widget-interaction.action.ts @@ -1,7 +1,7 @@ -import type { RunnableHooks, ActionPipe } from '@engine/action/action-pipeline'; +import type { ActionPipe, RunnableHooks } from '@engine/action/action-pipeline'; import type { ActionHook } from '@engine/action/hook/action-hook'; import { getActionHooks } from '@engine/action/hook/action-hook'; -import { questHookFilter, advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { advancedNumberHookFilter, questHookFilter } from '@engine/action/hook/hook-filters'; import type { Player } from '@engine/world/actor/player/player'; /** @@ -18,13 +18,11 @@ export interface WidgetInteractionActionHook extends ActionHook void; - /** * Details about a widget action being performed. */ @@ -39,7 +37,6 @@ export interface WidgetInteractionAction { optionId: number; } - /** * The pipe that the game engine hands widget actions off to. * @param player The player performing the action. @@ -47,33 +44,37 @@ export interface WidgetInteractionAction { * @param childId The ID of the widget child being interacted with. * @param optionId The widget context option chosen by the player. */ -const widgetActionPipe = (player: Player, widgetId: number, childId: number, optionId: number): RunnableHooks | null => { - const playerWidget = Object.values(player.interfaceState.widgetSlots) - .find((widget) => widget && widget.widgetId === widgetId); - - if(playerWidget?.fakeWidget) { +const widgetActionPipe = ( + player: Player, + widgetId: number, + childId: number, + optionId: number, +): RunnableHooks | null => { + const playerWidget = Object.values(player.interfaceState.widgetSlots).find(widget => widget && widget.widgetId === widgetId); + + if (playerWidget?.fakeWidget) { widgetId = playerWidget.fakeWidget; } // Find all item on item action plugins that match this action let matchingHooks = getActionHooks('widget_interaction').filter(plugin => { - if(!plugin.widgetIds) { + if (!plugin.widgetIds) { return false; } - if(!questHookFilter(player, plugin)) { + if (!questHookFilter(player, plugin)) { return false; } - if(!advancedNumberHookFilter(plugin.widgetIds, widgetId)) { + if (!advancedNumberHookFilter(plugin.widgetIds, widgetId)) { return false; } - if(plugin.optionId !== undefined && plugin.optionId !== optionId) { + if (plugin.optionId !== undefined && plugin.optionId !== optionId) { return false; } - if(plugin.childIds !== undefined) { + if (plugin.childIds !== undefined) { return advancedNumberHookFilter(plugin.childIds, childId); } return true; @@ -81,11 +82,11 @@ const widgetActionPipe = (player: Player, widgetId: number, childId: number, opt const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - if(questActions.length !== 0) { + if (questActions.length !== 0) { matchingHooks = questActions; } - if(matchingHooks.length === 0) { + if (matchingHooks.length === 0) { player.outgoingPackets.chatboxMessage(`Unhandled widget option: ${widgetId}, ${childId}:${optionId}`); return null; } @@ -94,12 +95,11 @@ const widgetActionPipe = (player: Player, widgetId: number, childId: number, opt return { hooks: matchingHooks, - action + action, }; }; - /** * Widget action pipe definition. */ -export default [ 'widget_interaction', widgetActionPipe ] as ActionPipe; +export default ['widget_interaction', widgetActionPipe] as ActionPipe; diff --git a/src/engine/config/config-handler.ts b/src/engine/config/config-handler.ts index a6d2816b0..a4b58351a 100644 --- a/src/engine/config/config-handler.ts +++ b/src/engine/config/config-handler.ts @@ -19,7 +19,6 @@ import { loadXteaRegionFiles } from '@runejs/filestore'; import { filestore } from '@server/game/game-server'; import _ from 'lodash'; - export let itemMap: { [key: string]: ItemDetails }; export let itemGroupMap: Record>; export let itemIdMap: { [key: number]: string }; @@ -64,23 +63,25 @@ export async function loadGameConfigurations(): Promise { objectMap = {}; - logger.info(`Loaded ${musicRegions.length} music regions, ${Object.keys(itemMap).length} items, ${itemSpawns.length} item spawns, ` + - `${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, and ${Object.keys(shopMap).length} shops.`); + logger.info( + `Loaded ${musicRegions.length} music regions, ${Object.keys(itemMap).length} items, ${itemSpawns.length} item spawns, ` + + `${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, and ${Object.keys(shopMap).length} shops.`, + ); } - /** * find all items in all select groups * @param groupKeys array of string of which to find items connected with * @return itemsKeys array of itemkeys in all select groups */ export const findItemTagsInGroups = (groupKeys: string[]): string[] => { - return Object.keys(groupKeys.reduce>((all, groupKey)=> { - const items = itemGroupMap[groupKey] || {}; - return { ...all, ...items }; - }, {})); -} - + return Object.keys( + groupKeys.reduce>((all, groupKey) => { + const items = itemGroupMap[groupKey] || {}; + return { ...all, ...items }; + }, {}), + ); +}; /** * find all items which are shared by all the groups, and discard items not in all groups @@ -88,57 +89,56 @@ export const findItemTagsInGroups = (groupKeys: string[]): string[] => { * @return itemKeys of items shared by all groups */ export const findItemTagsInGroupFilter = (groupKeys: string[]): string[] => { - if(!groupKeys || groupKeys.length === 0) { + if (!groupKeys || groupKeys.length === 0) { return []; } let collection: Record | undefined = undefined; - groupKeys.forEach((groupKey) => { - if(!collection) { + groupKeys.forEach(groupKey => { + if (!collection) { collection = { ...(itemGroupMap[groupKey] || {}) }; return; } const current = itemGroupMap[groupKey] || {}; - Object.keys(collection).forEach((existingItemKey) => { - if(!(existingItemKey in current) && collection) { + Object.keys(collection).forEach(existingItemKey => { + if (!(existingItemKey in current) && collection) { delete collection[existingItemKey]; } }); }); return Object.keys(collection || {}); -} - +}; export const findItem = (itemKey: number | string): ItemDetails | null => { - if(!itemKey) { + if (!itemKey) { return null; } let gameId: number | null = null; - if(typeof itemKey === 'number') { + if (typeof itemKey === 'number') { gameId = itemKey; itemKey = itemIdMap[gameId]; - if(!itemKey) { + if (!itemKey) { logger.warn(`Item ${gameId} is not yet registered on the server.`); } } let item; - if(itemKey) { + if (itemKey) { item = itemMap[itemKey]; - if(!item) { + if (!item) { // Try fetching variation with suffix 0 - item = itemMap[`${itemKey}:0`] + item = itemMap[`${itemKey}:0`]; } - if(item?.gameId) { + if (item?.gameId) { gameId = item.gameId; } } - if(gameId) { + if (gameId) { const cacheItem = filestore.configStore.itemStore.getItem(gameId); item = _.merge(item, cacheItem); } @@ -146,22 +146,21 @@ export const findItem = (itemKey: number | string): ItemDetails | null => { return item ? new ItemDetails(item) : null; }; - export const findNpc = (inputKey: number | string): NpcDetails => { - if(!inputKey) { + if (!inputKey) { throw new Error('No NPC was provided to findNpc.'); } // Pathway for finding an NPC by its game id - if(typeof inputKey === 'number') { + if (typeof inputKey === 'number') { const gameId = inputKey; const npcKey = npcIdMap[gameId]; // If we can't find a config in the project for this NPC - we fallback // to the cache which is the basic info loaded by `fileserver`. - if(!npcKey) { + if (!npcKey) { const cacheNpc = filestore.configStore.npcStore.getNpc(gameId); - if(cacheNpc) { + if (cacheNpc) { return cacheNpc; } else { logger.warn(`NPC ${gameId} is not yet configured on the server and a matching cache NPC was not found.`); @@ -172,25 +171,25 @@ export const findNpc = (inputKey: number | string): NpcDetails => { // Otherwise we got a string identifier for the npcs let npc = npcMap[inputKey]; - if(!npc) { + if (!npc) { // Try fetching variation with suffix 0 - npc = npcMap[`${npc}:0`] + npc = npcMap[`${npc}:0`]; } - if(!npc) { + if (!npc) { logger.warn(`NPC ${inputKey} is not yet configured on the server and a matching cache NPC was not provided.`); throw new Error(`NPC ${inputKey} is not yet configured on the server and a matching cache NPC was not provided.`); } - if(npc.extends) { + if (npc.extends) { let extensions = npc.extends; - if(typeof extensions === 'string') { - extensions = [ extensions ]; + if (typeof extensions === 'string') { + extensions = [extensions]; } extensions.forEach(extKey => { const extensionNpc = npcPresetMap[extKey]; - if(extensionNpc) { + if (extensionNpc) { npc = _.merge(npc, translateNpcServerConfig(undefined, extensionNpc)); } }); @@ -199,11 +198,10 @@ export const findNpc = (inputKey: number | string): NpcDetails => { return npc; }; - export const findObject = (objectId: number): ObjectConfig | null => { - if(!objectMap[objectId]) { + if (!objectMap[objectId]) { const object = filestore.objectStore.getObject(objectId); - if(!object) { + if (!object) { return null; } @@ -214,16 +212,14 @@ export const findObject = (objectId: number): ObjectConfig | null => { } }; - export const findShop = (shopKey: string): Shop | null => { - if(!shopKey) { + if (!shopKey) { return null; } return shopMap[shopKey] || null; }; - export const findQuest = (questId: string): Quest | null => { const questKey = Object.keys(questMap).find(quest => quest.toLocaleLowerCase() === questId.toLocaleLowerCase()); diff --git a/src/engine/config/data-dump.ts b/src/engine/config/data-dump.ts index 15c96342a..ce52864a8 100644 --- a/src/engine/config/data-dump.ts +++ b/src/engine/config/data-dump.ts @@ -1,20 +1,19 @@ -import { logger } from '@runejs/common'; -import type { NpcConfig, ItemConfig, ObjectConfig, WidgetBase } from '@runejs/filestore'; -import { filestore } from '@server/game/game-server'; import { writeFileSync } from 'fs'; import { join } from 'path'; +import { logger } from '@runejs/common'; +import type { ItemConfig, NpcConfig, ObjectConfig, WidgetBase } from '@runejs/filestore'; +import { filestore } from '@server/game/game-server'; export interface DataDumpResult { successful: boolean; filePath: string; } - function dump(fileName: string, definitions: T[]): DataDumpResult { const filePath = join('data/dump', fileName); const arr: T[] = []; - for(let i = 0; i < definitions.length; i++) { + for (let i = 0; i < definitions.length; i++) { arr.push(definitions[i]); } @@ -22,13 +21,13 @@ function dump(fileName: string, definitions: T[]): DataDumpResult { writeFileSync(filePath, JSON.stringify(arr, null, 4)); return { successful: true, - filePath + filePath, }; - } catch(error) { + } catch (error) { logger.error(`Error dumping ${fileName}`); return { successful: false, - filePath + filePath, }; } } diff --git a/src/engine/config/item-config.ts b/src/engine/config/item-config.ts index e128de027..877d09b91 100644 --- a/src/engine/config/item-config.ts +++ b/src/engine/config/item-config.ts @@ -3,49 +3,75 @@ import type { SkillName } from '@engine/world/actor/skills'; import { logger } from '@runejs/common'; import { loadConfigurationFiles } from '@runejs/common/fs'; -export type WeaponStyle = 'axe' | 'hammer' | 'bow' | 'claws' | 'crossbow' | 'gun' | 'slash_sword' - | '2h_sword' | 'pickaxe' | 'halberd' | 'polestaff' | 'scythe' | 'spear' | 'mace' - | 'dagger' | 'magical_staff' | 'darts' | 'unarmed' | 'whip'; +export type WeaponStyle = + | 'axe' + | 'hammer' + | 'bow' + | 'claws' + | 'crossbow' + | 'gun' + | 'slash_sword' + | '2h_sword' + | 'pickaxe' + | 'halberd' + | 'polestaff' + | 'scythe' + | 'spear' + | 'mace' + | 'dagger' + | 'magical_staff' + | 'darts' + | 'unarmed' + | 'whip'; export const weaponWidgetIds: Record = { - 'axe': 75, - 'hammer': 76, - 'bow': 77, - 'claws': 78, - 'crossbow': 79, - 'gun': 80, - 'slash_sword': 81, + axe: 75, + hammer: 76, + bow: 77, + claws: 78, + crossbow: 79, + gun: 80, + slash_sword: 81, '2h_sword': 82, - 'pickaxe': 83, - 'halberd': 84, - 'polestaff': 85, - 'scythe': 86, - 'spear': 87, - 'mace': 88, - 'dagger': 89, - 'magical_staff': 90, - 'darts': 91, - 'unarmed': 92, - 'whip': 93 + pickaxe: 83, + halberd: 84, + polestaff: 85, + scythe: 86, + spear: 87, + mace: 88, + dagger: 89, + magical_staff: 90, + darts: 91, + unarmed: 92, + whip: 93, }; - - -export type EquipmentSlot = 'head' | 'back' | 'neck' | 'main_hand' | 'off_hand' | 'torso' | - 'legs' | 'hands' | 'feet' | 'ring' | 'quiver' | '2h'; +export type EquipmentSlot = + | 'head' + | 'back' + | 'neck' + | 'main_hand' + | 'off_hand' + | 'torso' + | 'legs' + | 'hands' + | 'feet' + | 'ring' + | 'quiver' + | '2h'; export const equipmentIndices = { - 'head': 0, - 'back': 1, - 'neck': 2, - 'main_hand': 3, - 'torso': 4, - 'off_hand': 5, - 'legs': 7, - 'hands': 9, - 'feet': 10, - 'ring': 12, - 'quiver': 13 + head: 0, + back: 1, + neck: 2, + main_hand: 3, + torso: 4, + off_hand: 5, + legs: 7, + hands: 9, + feet: 10, + ring: 12, + quiver: 13, }; export const equipmentIndex = (equipmentSlot: EquipmentSlot): number => equipmentIndices[equipmentSlot]; @@ -113,7 +139,6 @@ export interface ItemMetadata { wikiId?: string; } - export interface EquipmentData { equipmentSlot: EquipmentSlot; equipmentType?: EquipmentType; @@ -133,9 +158,11 @@ export interface ItemConfiguration { game_id?: number; examine?: string; tradable?: boolean; - variations?: [{ - suffix: string; - } & ItemConfiguration]; + variations?: [ + { + suffix: string; + } & ItemConfiguration, + ]; weight?: number; equippable?: boolean; consumable?: boolean; @@ -184,7 +211,7 @@ export class ItemDetails { public constructor(item?: ItemDetails) { if (item) { const keys = Object.keys(item); - keys.forEach(key => this[key] = item[key]); + keys.forEach(key => (this[key] = item[key])); } } @@ -213,26 +240,30 @@ export function translateItemConfig(key: string | undefined, config: ItemConfigu destroy: config.destroy || undefined, groups: config.groups || [], consumable: config.consumable, - equipmentData: config.equipment_data ? { - equipmentType: config.equipment_data?.equipment_type || undefined, - equipmentSlot: config.equipment_data?.equipment_slot || undefined, - requirements: config.equipment_data?.requirements || undefined, - offensiveBonuses: config.equipment_data?.offensive_bonuses || undefined, - defensiveBonuses: config.equipment_data?.defensive_bonuses || undefined, - skillBonuses: config.equipment_data?.skill_bonuses || undefined, - weaponInfo: config.equipment_data?.weapon_info || undefined, - } : undefined, - metadata: config.metadata ? { ...config.metadata } : {} + equipmentData: config.equipment_data + ? { + equipmentType: config.equipment_data?.equipment_type || undefined, + equipmentSlot: config.equipment_data?.equipment_slot || undefined, + requirements: config.equipment_data?.requirements || undefined, + offensiveBonuses: config.equipment_data?.offensive_bonuses || undefined, + defensiveBonuses: config.equipment_data?.defensive_bonuses || undefined, + skillBonuses: config.equipment_data?.skill_bonuses || undefined, + weaponInfo: config.equipment_data?.weapon_info || undefined, + } + : undefined, + metadata: config.metadata ? { ...config.metadata } : {}, }; } export async function loadItemConfigurations(path: string): Promise<{ items: { [key: string]: ItemDetails }; - itemIds: { [key: number]: string }; itemPresets: ItemPresetConfiguration; itemGroups: Record>; + itemIds: { [key: number]: string }; + itemPresets: ItemPresetConfiguration; + itemGroups: Record>; }> { const itemIds: { [key: number]: string } = {}; const items: { [key: string]: ItemDetails } = {}; - const itemGroups: Record> = {} // Record where key is group id, and value is an array of all itemstags in group + const itemGroups: Record> = {}; // Record where key is group id, and value is an array of all itemstags in group let itemPresets: ItemPresetConfiguration = {}; const files = await loadConfigurationFiles(path); @@ -251,7 +282,7 @@ export async function loadItemConfigurations(path: string): Promise<{ Object.entries(itemConfigurations).forEach(([key, itemConfig]) => { if (itemConfig.game_id !== undefined && !isNaN(itemConfig.game_id)) { itemIds[itemConfig.game_id] = key; - let item = { ...translateItemConfig(key, itemConfig) } + let item = { ...translateItemConfig(key, itemConfig) }; if (item?.extends) { let extensions = item.extends; if (typeof extensions === 'string') { @@ -267,12 +298,12 @@ export async function loadItemConfigurations(path: string): Promise<{ }); } items[key] = item; - item.groups.forEach((group) => { + item.groups.forEach(group => { if (!itemGroups[group]) { itemGroups[group] = {}; } itemGroups[group][key] = true; - }) + }); } if (itemConfig.variations) { @@ -304,18 +335,18 @@ export async function loadItemConfigurations(path: string): Promise<{ }); } items[subKey] = item; - items[subKey].groups.forEach((group) => { + items[subKey].groups.forEach(group => { if (!itemGroups[group]) { itemGroups[group] = {}; } itemGroups[group][subKey] = true; - }) + }); } else { logger.warn(`Duplicate item key ${subKey} found - the item was not loaded.`); } } } - }) + }); return { items, itemIds, itemPresets, itemGroups }; } diff --git a/src/engine/config/item-spawn-config.ts b/src/engine/config/item-spawn-config.ts index 55edc7514..ac300d860 100644 --- a/src/engine/config/item-spawn-config.ts +++ b/src/engine/config/item-spawn-config.ts @@ -13,7 +13,6 @@ export interface ItemSpawnConfiguration { } export class ItemSpawn { - public itemKey: string; public amount: number = 1; public spawnPosition: Position; @@ -25,21 +24,20 @@ export class ItemSpawn { this.itemKey = itemKey; this.spawnPosition = position; } - } export function translateItemSpawnConfig(config: ItemSpawnConfiguration): ItemSpawn { const spawn = new ItemSpawn(config.item, new Position(config.spawn_x, config.spawn_y, config.spawn_level || 0)); - if(config.amount !== undefined) { + if (config.amount !== undefined) { spawn.amount = config.amount; } - if(config.instance !== undefined) { + if (config.instance !== undefined) { spawn.instance = config.instance; } - if(config.respawn !== undefined) { + if (config.respawn !== undefined) { spawn.respawn = config.respawn; } - if(config.metadata !== undefined) { + if (config.metadata !== undefined) { spawn.metadata = config.metadata; } diff --git a/src/engine/config/music-regions-config.ts b/src/engine/config/music-regions-config.ts index 35abf0665..c30d63c8d 100644 --- a/src/engine/config/music-regions-config.ts +++ b/src/engine/config/music-regions-config.ts @@ -7,9 +7,7 @@ export interface MusicRegionsConfiguration { regionIds: number[]; } - export class MusicTrack { - public songId: number; public songName: string; public musicTabButtonId: number; diff --git a/src/engine/config/npc-config.ts b/src/engine/config/npc-config.ts index 826846100..8a2060d3d 100644 --- a/src/engine/config/npc-config.ts +++ b/src/engine/config/npc-config.ts @@ -54,9 +54,11 @@ export interface NpcServerConfig { ranged_strength?: number; }; defensive_stats?: DefensiveBonuses; - variations?: [{ - suffix: string; - } & NpcServerConfig]; + variations?: [ + { + suffix: string; + } & NpcServerConfig, + ]; animations?: NpcCombatAnimations; drop_table?: DropTable[]; metadata: { [key: string]: unknown }; @@ -66,7 +68,6 @@ export interface NpcServerConfig { * Full server + cache details about a specific game NPC. */ export class NpcDetails extends NpcConfig { - extends?: string | string[]; key?: string; skills?: NpcSkills; @@ -80,9 +81,8 @@ export class NpcDetails extends NpcConfig { public constructor(defaultValues: { [key: string]: any }) { super(); - Object.keys(defaultValues).forEach(key => this[key] = defaultValues[key]); + Object.keys(defaultValues).forEach(key => (this[key] = defaultValues[key])); } - } export function translateNpcServerConfig(npcKey: string | undefined, config: NpcServerConfig): NpcDetails { @@ -92,34 +92,34 @@ export function translateNpcServerConfig(npcKey: string | undefined, config: Npc skills: config.skills || {}, killable: config.killable || false, respawnTime: config.respawn_time || 1, - offensiveStats: config.offensive_stats ? { - speed: config.offensive_stats.speed || undefined, - attack: config.offensive_stats.attack || undefined, - strength: config.offensive_stats.strength || undefined, - magic: config.offensive_stats.magic || undefined, - magicStrength: config.offensive_stats.magic_strength || undefined, - ranged: config.offensive_stats.ranged || undefined, - rangedStrength: config.offensive_stats.ranged_strength || undefined - } : undefined, + offensiveStats: config.offensive_stats + ? { + speed: config.offensive_stats.speed || undefined, + attack: config.offensive_stats.attack || undefined, + strength: config.offensive_stats.strength || undefined, + magic: config.offensive_stats.magic || undefined, + magicStrength: config.offensive_stats.magic_strength || undefined, + ranged: config.offensive_stats.ranged || undefined, + rangedStrength: config.offensive_stats.ranged_strength || undefined, + } + : undefined, defensiveStats: config.defensive_stats || undefined, combatAnimations: config.animations || {}, dropTable: config.drop_table || undefined, - metadata: config.metadata || {} + metadata: config.metadata || {}, }); } export async function loadNpcConfigurations(path: string): Promise<{ npcs: { [key: string]: NpcDetails }; - npcIds: { [key: number]: string }; npcPresets: NpcPresetConfiguration; + npcIds: { [key: number]: string }; + npcPresets: NpcPresetConfiguration; }> { const npcIds: { [key: number]: string } = {}; const npcs: { [key: string]: NpcDetails } = {}; let npcPresets: NpcPresetConfiguration = {}; - const files = await loadConfigurationFiles< - { presets: NpcPresetConfiguration | undefined } - & { [key: string]: NpcServerConfig } - >(path); + const files = await loadConfigurationFiles<{ presets: NpcPresetConfiguration | undefined } & { [key: string]: NpcServerConfig }>(path); files.forEach(npcConfigs => { const npcKeys = Object.keys(npcConfigs); @@ -132,22 +132,26 @@ export async function loadNpcConfigurations(path: string): Promise<{ npcIds[npcConfig.game_id] = key; npcs[key] = { ...translateNpcServerConfig(key, npcConfig), - ...filestore.configStore.npcStore.getNpc(npcConfig.game_id) + ...filestore.configStore.npcStore.getNpc(npcConfig.game_id), }; } if (npcConfig.variations) { for (const variation of npcConfig.variations) { try { const subKey = key + ':' + variation.suffix; - const baseItem = JSON.parse(JSON.stringify({ - ...translateNpcServerConfig(key, npcConfig), - ...filestore.configStore.npcStore.getNpc(npcConfig.game_id) - })); - - const subBaseItem = JSON.parse(JSON.stringify({ - ...translateNpcServerConfig(subKey, variation), - ...filestore.configStore.npcStore.getNpc(variation.game_id) - })); + const baseItem = JSON.parse( + JSON.stringify({ + ...translateNpcServerConfig(key, npcConfig), + ...filestore.configStore.npcStore.getNpc(npcConfig.game_id), + }), + ); + + const subBaseItem = JSON.parse( + JSON.stringify({ + ...translateNpcServerConfig(subKey, variation), + ...filestore.configStore.npcStore.getNpc(variation.game_id), + }), + ); npcIds[variation.game_id] = subKey; npcs[subKey] = _.merge(baseItem, subBaseItem); } catch (error) { diff --git a/src/engine/config/npc-spawn-config.ts b/src/engine/config/npc-spawn-config.ts index 323c75714..537a402b1 100644 --- a/src/engine/config/npc-spawn-config.ts +++ b/src/engine/config/npc-spawn-config.ts @@ -1,7 +1,6 @@ +import type { Direction } from '@engine/world/direction'; import { Position } from '@engine/world/position'; import { loadConfigurationFiles } from '@runejs/common/fs'; -import type { Direction } from '@engine/world/direction'; - export interface NpcSpawnConfiguration { npc: string; @@ -13,25 +12,26 @@ export interface NpcSpawnConfiguration { } export class NpcSpawn { - public npcKey: string; public spawnPosition: Position; public movementRadius: number; public faceDirection: Direction; - public constructor(npcKey: string, spawnPosition: Position, movementRadius: number = 0, - faceDirection: Direction = 'WEST') { + public constructor(npcKey: string, spawnPosition: Position, movementRadius: number = 0, faceDirection: Direction = 'WEST') { this.npcKey = npcKey; this.spawnPosition = spawnPosition; this.movementRadius = movementRadius; this.faceDirection = faceDirection; } - } export function translateNpcSpawnConfig(config: NpcSpawnConfiguration): NpcSpawn { - return new NpcSpawn(config.npc, new Position(config.spawn_x, config.spawn_y, config.spawn_level || 0), - config.movement_radius || 0, config.face || 'WEST'); + return new NpcSpawn( + config.npc, + new Position(config.spawn_x, config.spawn_y, config.spawn_level || 0), + config.movement_radius || 0, + config.face || 'WEST', + ); } export async function loadNpcSpawnConfigurations(path: string): Promise { diff --git a/src/engine/config/quest-config.ts b/src/engine/config/quest-config.ts index 50940ea68..c3cfb6d85 100644 --- a/src/engine/config/quest-config.ts +++ b/src/engine/config/quest-config.ts @@ -40,21 +40,23 @@ export class PlayerQuest { } } -export function questDialogueActionFactory(questId: string, - npcDialogueHandler: QuestDialogueHandler, - stageHandler: (player: Player) => Promise): npcInteractionActionHandler { - return async({ player, npc }) => { +export function questDialogueActionFactory( + questId: string, + npcDialogueHandler: QuestDialogueHandler, + stageHandler: (player: Player) => Promise, +): npcInteractionActionHandler { + return async ({ player, npc }) => { const quest = player.getQuest(questId); - if(!quest) { + if (!quest) { return; } const progress = quest.progress; const dialogueHandler = npcDialogueHandler[progress]; - if(dialogueHandler) { + if (dialogueHandler) { try { await dialogueHandler(player, npc); - } catch(e) { + } catch (e) { logger.error(e); } diff --git a/src/engine/config/shop-config.test.ts b/src/engine/config/shop-config.test.ts index 8942cf34d..30dfe8d9f 100644 --- a/src/engine/config/shop-config.test.ts +++ b/src/engine/config/shop-config.test.ts @@ -1,10 +1,9 @@ +import { findItem } from '@engine/config/config-handler'; import type { Shop, ShopConfiguration } from '@engine/config/shop-config'; import { shopFactory } from '@engine/config/shop-config'; -import { findItem } from '@engine/config/config-handler'; import { setupConfig } from '@server/game/game-server'; describe('shopping', () => { - const shopConfig: ShopConfiguration = { name: 'Test Shop', general_store: false, @@ -15,41 +14,40 @@ describe('shopping', () => { { itemKey: 'rs:battlestaff', amount: 5, - restock: 100 + restock: 100, }, { itemKey: 'rs:staff', amount: 5, - restock: 100 + restock: 100, }, { itemKey: 'rs:magic_staff', amount: 5, - restock: 200 + restock: 200, }, { itemKey: 'rs:staff_of_air', amount: 2, - restock: 1000 + restock: 1000, }, { itemKey: 'rs:staff_of_water', amount: 2, - restock: 1000 + restock: 1000, }, { itemKey: 'rs:staff_of_earth', amount: 2, - restock: 1000 + restock: 1000, }, { itemKey: 'rs:staff_of_fire', amount: 2, - restock: 1000 - } - ] - - } + restock: 1000, + }, + ], + }; const shopname = 'rs:test_shop'; let shop: Shop; @@ -57,23 +55,24 @@ describe('shopping', () => { beforeAll(async () => { world = await setupConfig(); - }) + }); beforeEach(() => { shop = shopFactory(shopname, shopConfig); - }) + }); describe('shop object', () => { test('shop should exist', () => { expect(shop?.key).toEqual(shopname); - }) + }); test('shop stock should be correct', () => { - expect(shopConfig.stock.reduce((all, curr) => all && shop.isItemSoldHere(curr.itemKey), true)).toBeTruthy() - expect(shop.isItemSoldHere('rs:salmon')).toBeFalsy() - }) - test('player should buy item from shop at correct value', () => { // Player purchases, shop sells + expect(shopConfig.stock.reduce((all, curr) => all && shop.isItemSoldHere(curr.itemKey), true)).toBeTruthy(); + expect(shop.isItemSoldHere('rs:salmon')).toBeFalsy(); + }); + test('player should buy item from shop at correct value', () => { + // Player purchases, shop sells - console.log(shop.container.items.map(a => a?.itemId)) + console.log(shop.container.items.map(a => a?.itemId)); const battleStaffItem = findItem('rs:battlestaff'); if (!battleStaffItem) { @@ -84,19 +83,18 @@ describe('shopping', () => { if (!shopBstaff) { throw new Error('Battle staff item not found in shop config'); } - expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(Math.round(battleStaffItem.value * (shopConfig.shop_sell_rate || 1.00))) - expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(7000) // BStaff standard price - expect(shopBstaff.amount).toBe(5) + expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(Math.round(battleStaffItem.value * (shopConfig.shop_sell_rate || 1.0))); + expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(7000); // BStaff standard price + expect(shopBstaff.amount).toBe(5); shopBstaff.amount += 1; - expect(shopBstaff.amount).toBe(6) + expect(shopBstaff.amount).toBe(6); expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(6860); shopBstaff.amount -= 3; - expect(shopBstaff.amount).toBe(3) + expect(shopBstaff.amount).toBe(3); expect(shop.getBuyFromShopPrice(battleStaffItem)).toBe(7280); - - - }) - test('shop should sell at correct value', () => { // Player sells, shop pays + }); + test('shop should sell at correct value', () => { + // Player sells, shop pays const battleStaffItem = findItem('rs:battlestaff'); if (!battleStaffItem) { @@ -110,24 +108,23 @@ describe('shopping', () => { // shopSpade.amount = 2; - - expect(shopBstaff.amount).toBe(5) - expect(shop.getSellToShopPrice(battleStaffItem)).toBe(3850) + expect(shopBstaff.amount).toBe(5); + expect(shop.getSellToShopPrice(battleStaffItem)).toBe(3850); shopBstaff.amount = 4; - expect(shopBstaff.amount).toBe(4) - expect(shop.getSellToShopPrice(battleStaffItem)).toBe(3990) + expect(shopBstaff.amount).toBe(4); + expect(shop.getSellToShopPrice(battleStaffItem)).toBe(3990); shopBstaff.amount = 1; - expect(shopBstaff.amount).toBe(1) - expect(shop.getSellToShopPrice(battleStaffItem)).toBe(4410) + expect(shopBstaff.amount).toBe(1); + expect(shop.getSellToShopPrice(battleStaffItem)).toBe(4410); shopBstaff.amount = 16; - expect(shopBstaff.amount).toBe(16) - expect(shop.getSellToShopPrice(battleStaffItem)).toBe(2310) + expect(shopBstaff.amount).toBe(16); + expect(shop.getSellToShopPrice(battleStaffItem)).toBe(2310); shopBstaff.amount = 3; - expect(shopBstaff.amount).toBe(3) - expect(shop.getSellToShopPrice(battleStaffItem)).toBe(4130) - }) - }) -}) + expect(shopBstaff.amount).toBe(3); + expect(shop.getSellToShopPrice(battleStaffItem)).toBe(4130); + }); + }); +}); diff --git a/src/engine/config/shop-config.ts b/src/engine/config/shop-config.ts index 5dc1f89ff..bc9656cd8 100644 --- a/src/engine/config/shop-config.ts +++ b/src/engine/config/shop-config.ts @@ -1,17 +1,15 @@ +import { findItem, widgets } from '@engine/config/config-handler'; +import type { ItemDetails } from '@engine/config/item-config'; +import type { WidgetClosedEvent } from '@engine/interface/interface-state'; +import type { Player } from '@engine/world/actor/player/player'; import type { ContainerUpdateEvent } from '@engine/world/items/item-container'; import { ItemContainer } from '@engine/world/items/item-container'; -import { findItem, widgets } from '@engine/config/config-handler'; import { loadConfigurationFiles } from '@runejs/common/fs'; -import type { Player } from '@engine/world/actor/player/player'; -import type { ItemDetails } from '@engine/config/item-config'; import type { Subscription } from 'rxjs'; -import type { WidgetClosedEvent } from '@engine/interface/interface-state'; - -export type ShopStock = { itemKey: string, amount: number, restock?: number }[]; +export type ShopStock = { itemKey: string; amount: number; restock?: number }[]; export class Shop { - public readonly key: string; public readonly originalStock: ShopStock; public readonly container: ItemContainer; @@ -25,7 +23,15 @@ export class Shop { private customers: Player[]; private containerSubscription: Subscription; - public constructor(key: string, name: string, generalStore: boolean, stock: ShopStock, sellRate: number, buyRate: number, modifier: number) { + public constructor( + key: string, + name: string, + generalStore: boolean, + stock: ShopStock, + sellRate: number, + buyRate: number, + modifier: number, + ) { this.key = key; this.name = name; this.generalStore = generalStore; @@ -70,7 +76,6 @@ export class Shop { originalStockAmount = foundStock.amount; } } else { - return -1; // Cannot buy from this shop } @@ -78,16 +83,16 @@ export class Shop { if (itemStock === originalStockAmount) { finalAmount = Math.round(item.value * this.sellRate); } else if (itemStock > originalStockAmount) { - const overstockAmount = (itemStock - originalStockAmount); + const overstockAmount = itemStock - originalStockAmount; let shopSellRate = this.sellRate; - shopSellRate -= (this.rateModifier * overstockAmount); + shopSellRate -= this.rateModifier * overstockAmount; finalAmount = item.value * shopSellRate; finalAmount = Math.round(finalAmount); } else { - const understockAmount = (originalStockAmount - itemStock); + const understockAmount = originalStockAmount - itemStock; let shopSellRate = this.sellRate; - shopSellRate += (this.rateModifier * understockAmount); + shopSellRate += this.rateModifier * understockAmount; finalAmount = item.value * shopSellRate; finalAmount = Math.round(finalAmount); @@ -107,7 +112,6 @@ export class Shop { let originalStockAmount: number = 0; const itemStock = this.container.amount(item.gameId); - if (itemSoldHere) { originalStockAmount = this.originalStock.find(stock => stock && stock.itemKey === itemKey)?.amount || 0; } else if (!this.generalStore) { @@ -119,16 +123,16 @@ export class Shop { if (itemStock === originalStockAmount) { finalAmount = Math.round(item.value * this.buyRate); } else if (itemStock > originalStockAmount) { - const overstockAmount = (itemStock - originalStockAmount); + const overstockAmount = itemStock - originalStockAmount; let shopBuyRate = this.buyRate; - shopBuyRate -= (this.rateModifier * overstockAmount); + shopBuyRate -= this.rateModifier * overstockAmount; finalAmount = item.value * shopBuyRate; finalAmount = Math.round(finalAmount); } else { - const understockAmount = (originalStockAmount - itemStock); + const understockAmount = originalStockAmount - itemStock; let shopBuyRate = this.buyRate; - shopBuyRate += (this.rateModifier * understockAmount); + shopBuyRate += this.rateModifier * understockAmount; finalAmount = item.value * shopBuyRate; finalAmount = Math.round(finalAmount); @@ -156,11 +160,11 @@ export class Shop { player.interfaceState.openWidget(widgets.shop.widgetId, { slot: 'screen', - multi: true + multi: true, }); player.interfaceState.openWidget(widgets.shopPlayerInventory.widgetId, { slot: 'tabarea', - multi: true + multi: true, }); this.customers.push(player); } @@ -180,7 +184,7 @@ export class Shop { delete player.metadata.lastOpenedShopKey; player.metadata.shopCloseListener?.unsubscribe(); } - this.customers = this.customers.filter((c) => c !== player); + this.customers = this.customers.filter(c => c !== player); } } @@ -194,8 +198,15 @@ export interface ShopConfiguration { } export function shopFactory(key: string, config: ShopConfiguration): Shop { - return new Shop(key, config.name, config.general_store || false, config.stock, - config.shop_sell_rate || 1.00, config.shop_buy_rate || 0.65, config.rate_modifier || 0.2); + return new Shop( + key, + config.name, + config.general_store || false, + config.stock, + config.shop_sell_rate || 1.0, + config.shop_buy_rate || 0.65, + config.rate_modifier || 0.2, + ); } export async function loadShopConfigurations(path: string): Promise<{ [key: string]: Shop }> { diff --git a/src/engine/interface/interface-state.ts b/src/engine/interface/interface-state.ts index 513a54386..3af3c0370 100644 --- a/src/engine/interface/interface-state.ts +++ b/src/engine/interface/interface-state.ts @@ -1,33 +1,42 @@ import type { Player } from '@engine/world/actor/player/player'; import type { ItemContainer } from '@engine/world/items/item-container'; import { logger } from '@runejs/common'; -import { lastValueFrom, Subject } from 'rxjs'; +import { Subject, lastValueFrom } from 'rxjs'; import { filter, take } from 'rxjs/operators'; - -export type TabType = 'combat' | 'skills' | 'quests' | 'inventory' | 'equipment' | 'prayers' | - 'spells' | 'friends' | 'ignores' | 'logout' | 'emotes' | 'settings' | 'music'; +export type TabType = + | 'combat' + | 'skills' + | 'quests' + | 'inventory' + | 'equipment' + | 'prayers' + | 'spells' + | 'friends' + | 'ignores' + | 'logout' + | 'emotes' + | 'settings' + | 'music'; export type GameInterfaceSlot = 'full' | 'screen' | 'chatbox' | 'tabarea'; - export const tabIndex: { [key: string]: number } = { - 'combat': 0, - 'skills': 1, - 'quests': 2, - 'inventory': 3, - 'equipment': 4, - 'prayers': 5, - 'spells': 6, - 'friends': 8, - 'ignores': 9, - 'logout': 10, - 'emotes': 11, - 'settings': 12, - 'music': 13 + combat: 0, + skills: 1, + quests: 2, + inventory: 3, + equipment: 4, + prayers: 5, + spells: 6, + friends: 8, + ignores: 9, + logout: 10, + emotes: 11, + settings: 12, + music: 13, }; - export interface WidgetOptions { slot: GameInterfaceSlot; multi?: boolean; @@ -38,9 +47,7 @@ export interface WidgetOptions { metadata?: { [key: string]: any }; } - export class Widget { - public widgetId: number; public slot: GameInterfaceSlot; public multi: boolean = false; @@ -60,9 +67,8 @@ export class Widget { this.queued = queued || false; this.containerId = containerId || -1; this.container = container || null; - this.metadata = { ...metadata } + this.metadata = { ...metadata }; } - } export interface WidgetClosedEvent { @@ -75,7 +81,6 @@ export interface WidgetClosedEvent { * Control's a Player's Game Interface state. */ export class InterfaceState { - public readonly tabs: { [key: string]: Widget | null }; public readonly widgetSlots: { [key: string]: Widget | null }; public readonly closed: Subject = new Subject(); @@ -85,19 +90,19 @@ export class InterfaceState { public constructor(player: Player) { this.tabs = { - 'combat': null, - 'skills': null, - 'quests': null, - 'inventory': null, - 'equipment': null, - 'prayers': null, - 'spells': null, - 'friends': null, - 'ignores': null, - 'logout': null, - 'emotes': null, - 'settings': null, - 'music': null + combat: null, + skills: null, + quests: null, + inventory: null, + equipment: null, + prayers: null, + spells: null, + friends: null, + ignores: null, + logout: null, + emotes: null, + settings: null, + music: null, }; this.widgetSlots = {}; @@ -129,8 +134,12 @@ export class InterfaceState { } public async widgetClosed(slot: GameInterfaceSlot): Promise { - return await lastValueFrom(this.closed.asObservable().pipe( - filter(event => event.widget.slot === slot)).pipe(take(1))); + return await lastValueFrom( + this.closed + .asObservable() + .pipe(filter(event => event.widget.slot === slot)) + .pipe(take(1)), + ); } public closeWidget(slot: GameInterfaceSlot, widgetId?: number, data?: number): void { @@ -146,7 +155,7 @@ export class InterfaceState { widget = this.findWidget(widgetId); } - if(!widget) { + if (!widget) { return; } @@ -161,11 +170,11 @@ export class InterfaceState { const widget = new Widget(widgetId, options); - if(widget.queued) { + if (widget.queued) { // @TODO queued widgets } - if(widget.slot === 'full' || !widget.multi) { + if (widget.slot === 'full' || !widget.multi) { this.clearSlots(); } @@ -175,24 +184,24 @@ export class InterfaceState { } public setTab(type: TabType, widget: Widget | number | null): void { - if(widget && typeof widget === 'number') { + if (widget && typeof widget === 'number') { // Create a new tab interface instance let container: ItemContainer | undefined; - if(type === 'inventory') { + if (type === 'inventory') { container = this.player.inventory; - } else if(type === 'equipment') { + } else if (type === 'equipment') { container = this.player.equipment; } widget = new Widget(widget, { slot: 'tabarea', multi: true, - container + container, }); } - widget = widget as Widget || null; + widget = (widget as Widget) || null; this.tabs[type] = widget; this.player.outgoingPackets.sendTabWidget(tabIndex[type], widget === null ? -1 : widget.widgetId); @@ -206,7 +215,7 @@ export class InterfaceState { const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) as GameInterfaceSlot[]; let widget: Widget | null = null; slots.forEach(slot => { - if(this.widgetSlots[slot]?.widgetId === widgetId) { + if (this.widgetSlots[slot]?.widgetId === widgetId) { widget = this.widgetSlots[slot]; } }); @@ -214,12 +223,12 @@ export class InterfaceState { } public widgetOpen(slot?: GameInterfaceSlot, widgetId?: number): boolean { - if(!slot) { + if (!slot) { const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) as GameInterfaceSlot[]; return slots.some(s => this.getWidget(s) !== null); } - if(widgetId === undefined) { + if (widgetId === undefined) { return this.getWidget(slot) !== null; } else { return this.getWidget(slot)?.widgetId === widgetId; @@ -240,28 +249,28 @@ export class InterfaceState { const { outgoingPackets: packets } = this.player; const { widgetId, containerId, slot, multi } = widget; - if(slot === 'full' || !multi) { + if (slot === 'full' || !multi) { this.closeOthers(slot); } - if(slot === 'full' && containerId !== undefined) { + if (slot === 'full' && containerId !== undefined) { packets.showFullscreenWidget(widgetId, containerId); - } else if(slot === 'screen') { + } else if (slot === 'screen') { const tabWidget = this.getWidget('tabarea'); - if(multi && tabWidget) { + if (multi && tabWidget) { packets.showScreenAndTabWidgets(widgetId, tabWidget.widgetId); } else { packets.showStandaloneScreenWidget(widgetId); } - } else if(slot === 'chatbox') { - if(multi) { + } else if (slot === 'chatbox') { + if (multi) { // Dialogue Widget packets.showChatDialogue(widgetId); } else { // Chatbox Widget packets.showChatboxWidget(widgetId); } - } else if(slot === 'tabarea') { + } else if (slot === 'tabarea') { const screenWidget = this.getWidget('screen'); if (!screenWidget) { @@ -269,7 +278,7 @@ export class InterfaceState { return; } - if(multi) { + if (multi) { packets.showScreenAndTabWidgets(screenWidget.widgetId, widgetId); } else { packets.showTabWidget(widgetId); @@ -278,8 +287,7 @@ export class InterfaceState { } private closeOthers(openSlot: GameInterfaceSlot): void { - const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) - .filter(slot => slot !== openSlot) as GameInterfaceSlot[]; + const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots).filter(slot => slot !== openSlot) as GameInterfaceSlot[]; slots.forEach(slot => this.closeWidget(slot)); } diff --git a/src/engine/net/inbound-packet-handler.ts b/src/engine/net/inbound-packet-handler.ts index 519066438..8d4827f45 100644 --- a/src/engine/net/inbound-packet-handler.ts +++ b/src/engine/net/inbound-packet-handler.ts @@ -1,8 +1,8 @@ +import { BUILD_DIR } from '@engine/config/directories'; +import type { Player } from '@engine/world/actor/player/player'; import type { ByteBuffer } from '@runejs/common'; import { logger } from '@runejs/common'; import { getFiles } from '../util/files'; -import type { Player } from '@engine/world/actor/player/player'; -import { BUILD_DIR } from '@engine/config/directories'; interface InboundPacket { opcode: number; @@ -23,7 +23,7 @@ export const PACKET_DIRECTORY = `${BUILD_DIR}/net/inbound-packets`; export async function loadPackets(): Promise> { incomingPackets.clear(); - for await(const path of getFiles(PACKET_DIRECTORY, ['.packet.js'], true)) { + for await (const path of getFiles(PACKET_DIRECTORY, ['.packet.js'], true)) { const location = './inbound-packets' + path.substring(PACKET_DIRECTORY.length).replace('.js', ''); const packet = require(location).default; if (Array.isArray(packet)) { @@ -39,7 +39,7 @@ export async function loadPackets(): Promise> { export function handlePacket(player: Player, packetId: number, packetSize: number, buffer: ByteBuffer): boolean { const incomingPacket = incomingPackets.get(packetId); - if(!incomingPacket) { + if (!incomingPacket) { logger.info(`Unknown packet ${packetId} with size ${packetSize} received.`); return false; } @@ -47,7 +47,7 @@ export function handlePacket(player: Player, packetId: number, packetSize: numbe new Promise(resolve => { try { incomingPacket.handler(player, { packetId, packetSize, buffer }); - } catch(error) { + } catch (error) { logger.error(`Error handling inbound packet ${packetId} with size ${packetSize}`); logger.error(error); } diff --git a/src/engine/net/inbound-packets/add-friend.packet.ts b/src/engine/net/inbound-packets/add-friend.packet.ts index f32b3ccc1..0a5b4bc53 100644 --- a/src/engine/net/inbound-packets/add-friend.packet.ts +++ b/src/engine/net/inbound-packets/add-friend.packet.ts @@ -2,10 +2,8 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; import { longToString } from '@engine/util/strings'; import type { Player } from '@engine/world/actor/player/player'; - export default { opcode: 114, size: 8, - handler: (player: Player, packet: PacketData) => - player.addFriend(longToString(BigInt(packet.buffer.get('LONG')))) + handler: (player: Player, packet: PacketData) => player.addFriend(longToString(BigInt(packet.buffer.get('LONG')))), }; diff --git a/src/engine/net/inbound-packets/add-ignore.packet.ts b/src/engine/net/inbound-packets/add-ignore.packet.ts index d509427f6..f5d32a123 100644 --- a/src/engine/net/inbound-packets/add-ignore.packet.ts +++ b/src/engine/net/inbound-packets/add-ignore.packet.ts @@ -5,6 +5,5 @@ import type { Player } from '@engine/world/actor/player/player'; export default { opcode: 251, size: 8, - handler: (player: Player, packet: PacketData) => - player.addIgnoredPlayer(longToString(BigInt(packet.buffer.get('LONG')))) + handler: (player: Player, packet: PacketData) => player.addIgnoredPlayer(longToString(BigInt(packet.buffer.get('LONG')))), }; diff --git a/src/engine/net/inbound-packets/blinking-tab-click.packet.ts b/src/engine/net/inbound-packets/blinking-tab-click.packet.ts index 06ec41bec..117af120a 100644 --- a/src/engine/net/inbound-packets/blinking-tab-click.packet.ts +++ b/src/engine/net/inbound-packets/blinking-tab-click.packet.ts @@ -7,7 +7,7 @@ const blinkingTabClickPacket = (player: Player, packet: PacketData) => { const tabClickEventIndex = player.metadata?.tabClickEvent?.tabIndex || -1; - if(tabClickEventIndex === tabIndex) { + if (tabClickEventIndex === tabIndex) { if (player.metadata.tabClickEvent) { player.metadata.tabClickEvent.event.next(true); } @@ -17,5 +17,5 @@ const blinkingTabClickPacket = (player: Player, packet: PacketData) => { export default { opcode: 44, size: 1, - handler: blinkingTabClickPacket + handler: blinkingTabClickPacket, }; diff --git a/src/engine/net/inbound-packets/button-click.packet.ts b/src/engine/net/inbound-packets/button-click.packet.ts index ca999b192..7b7e4a671 100644 --- a/src/engine/net/inbound-packets/button-click.packet.ts +++ b/src/engine/net/inbound-packets/button-click.packet.ts @@ -12,5 +12,5 @@ const buttonClickPacket = (player: Player, packet: PacketData) => { export default { opcode: 64, size: 4, - handler: buttonClickPacket + handler: buttonClickPacket, }; diff --git a/src/engine/net/inbound-packets/character-design.packet.ts b/src/engine/net/inbound-packets/character-design.packet.ts index 54f7a3c7d..6799dc51e 100644 --- a/src/engine/net/inbound-packets/character-design.packet.ts +++ b/src/engine/net/inbound-packets/character-design.packet.ts @@ -10,11 +10,11 @@ const characterDesignPacket = (player: Player, packet: PacketData) => { const models = new Array(7); const colors = new Array(5); - for(let i = 0; i < models.length; i++) { + for (let i = 0; i < models.length; i++) { models[i] = buffer.get('byte'); } - for(let i = 0; i < colors.length; i++) { + for (let i = 0; i < colors.length; i++) { colors[i] = buffer.get('byte'); } @@ -31,7 +31,7 @@ const characterDesignPacket = (player: Player, packet: PacketData) => { torsoColor: colors[1], legColor: colors[2], feetColor: colors[3], - skinColor: colors[4] + skinColor: colors[4], }; player.updateFlags.appearanceUpdateRequired = true; @@ -41,5 +41,5 @@ const characterDesignPacket = (player: Player, packet: PacketData) => { export default { opcode: 231, size: 13, - handler: characterDesignPacket + handler: characterDesignPacket, }; diff --git a/src/engine/net/inbound-packets/chat.packet.ts b/src/engine/net/inbound-packets/chat.packet.ts index a330b425c..a00357844 100644 --- a/src/engine/net/inbound-packets/chat.packet.ts +++ b/src/engine/net/inbound-packets/chat.packet.ts @@ -13,5 +13,5 @@ const chatPacket = (player: Player, packet: PacketData) => { export default { opcode: 75, size: -3, - handler: chatPacket + handler: chatPacket, }; diff --git a/src/engine/net/inbound-packets/command.packet.ts b/src/engine/net/inbound-packets/command.packet.ts index 779e0c191..8212abad1 100644 --- a/src/engine/net/inbound-packets/command.packet.ts +++ b/src/engine/net/inbound-packets/command.packet.ts @@ -1,10 +1,10 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; -import { Rights, type Player } from '@engine/world/actor/player/player'; +import { type Player, Rights } from '@engine/world/actor/player/player'; const commandPacket = (player: Player, packet: PacketData) => { const input = packet.buffer.getString(); - if(!input || input.trim().length === 0) { + if (!input || input.trim().length === 0) { return; } @@ -14,19 +14,22 @@ const commandPacket = (player: Player, packet: PacketData) => { const command = args[0]; args.splice(0, 1); - if(player.rights !== Rights.ADMIN) { + if (player.rights !== Rights.ADMIN) { player.sendLogMessage('You need to be an administrator to use commands.', isConsole); } else { player.actionPipeline.call('player_command', player, command, isConsole, args); } }; -export default [{ - opcode: 246, - size: -3, - handler: commandPacket -},{ - opcode: 248, - size: -1, - handler: commandPacket -}]; +export default [ + { + opcode: 246, + size: -3, + handler: commandPacket, + }, + { + opcode: 248, + size: -1, + handler: commandPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/drop-item.packet.ts b/src/engine/net/inbound-packets/drop-item.packet.ts index 8ddee715e..5d39f90be 100644 --- a/src/engine/net/inbound-packets/drop-item.packet.ts +++ b/src/engine/net/inbound-packets/drop-item.packet.ts @@ -14,5 +14,5 @@ const dropItemPacket = (player: Player, packet: PacketData) => { export default { opcode: 29, size: 8, - handler: dropItemPacket + handler: dropItemPacket, }; diff --git a/src/engine/net/inbound-packets/examine.packet.ts b/src/engine/net/inbound-packets/examine.packet.ts index 5e10af323..0e6eea13b 100644 --- a/src/engine/net/inbound-packets/examine.packet.ts +++ b/src/engine/net/inbound-packets/examine.packet.ts @@ -1,6 +1,6 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; -import type { Player } from '@engine/world/actor/player/player'; import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; const examinePacket = (player: Player, packet: PacketData) => { const { packetId, buffer } = packet; @@ -8,29 +8,33 @@ const examinePacket = (player: Player, packet: PacketData) => { let message; - if(packetId === 151) { + if (packetId === 151) { message = activeWorld.examine.getItem(id); - } else if(packetId === 148) { + } else if (packetId === 148) { message = activeWorld.examine.getObject(id); - } else if(packetId === 247) { + } else if (packetId === 247) { message = activeWorld.examine.getNpc(id); } - if(message) { + if (message) { player.sendMessage(message); } }; -export default [ { - opcode: 148, - size: 2, - handler: examinePacket -}, { - opcode: 151, - size: 2, - handler: examinePacket -}, { - opcode: 247, - size: 2, - handler: examinePacket -} ]; +export default [ + { + opcode: 148, + size: 2, + handler: examinePacket, + }, + { + opcode: 151, + size: 2, + handler: examinePacket, + }, + { + opcode: 247, + size: 2, + handler: examinePacket, + }, +]; diff --git a/src/engine/net/inbound-packets/item-interaction.packet.ts b/src/engine/net/inbound-packets/item-interaction.packet.ts index aceaf8f03..66c82fd35 100644 --- a/src/engine/net/inbound-packets/item-interaction.packet.ts +++ b/src/engine/net/inbound-packets/item-interaction.packet.ts @@ -78,32 +78,40 @@ const itemInteractionPacket = (player: Player, packet: PacketData) => { player.actionPipeline.call('item_interaction', player, itemId, slot, widgetId, containerId, option); }; -export default [{ - opcode: 38, - size: 8, - handler: itemInteractionPacket -},{ - opcode: 98, - size: 8, - handler: itemInteractionPacket -},{ - opcode: 228, - size: 8, - handler: itemInteractionPacket -},{ - opcode: 26, - size: 8, - handler: itemInteractionPacket -},{ - opcode: 147, - size: 8, - handler: itemInteractionPacket -},{ - opcode: 240, - size: 8, - handler: itemInteractionPacket -}, { - opcode: 102, - size: 8, - handler: itemInteractionPacket -}]; +export default [ + { + opcode: 38, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 98, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 228, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 26, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 147, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 240, + size: 8, + handler: itemInteractionPacket, + }, + { + opcode: 102, + size: 8, + handler: itemInteractionPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/item-on-item.packet.ts b/src/engine/net/inbound-packets/item-on-item.packet.ts index 5c85017fe..3dd8cb54e 100644 --- a/src/engine/net/inbound-packets/item-on-item.packet.ts +++ b/src/engine/net/inbound-packets/item-on-item.packet.ts @@ -1,7 +1,7 @@ -import { logger } from '@runejs/common'; +import { widgets } from '@engine/config/config-handler'; import type { PacketData } from '@engine/net/inbound-packet-handler'; import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; const itemOnItemPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -14,31 +14,36 @@ const itemOnItemPacket = (player: Player, packet: PacketData) => { const usedItemId = buffer.get('short', 'u', 'le'); const usedSlot = buffer.get('short', 'u'); - if(usedWidgetId === widgets.inventory.widgetId && usedContainerId === widgets.inventory.containerId && - usedWithWidgetId === widgets.inventory.widgetId && usedWithContainerId === widgets.inventory.containerId) { - if(usedSlot < 0 || usedSlot > 27 || usedWithSlot < 0 || usedWithSlot > 27) { + if ( + usedWidgetId === widgets.inventory.widgetId && + usedContainerId === widgets.inventory.containerId && + usedWithWidgetId === widgets.inventory.widgetId && + usedWithContainerId === widgets.inventory.containerId + ) { + if (usedSlot < 0 || usedSlot > 27 || usedWithSlot < 0 || usedWithSlot > 27) { return; } const usedItem = player.inventory.items[usedSlot]; const usedWithItem = player.inventory.items[usedWithSlot]; - if(!usedItem || !usedWithItem) { + if (!usedItem || !usedWithItem) { return; } - if(usedItem.itemId !== usedItemId || usedWithItem.itemId !== usedWithItemId) { + if (usedItem.itemId !== usedItemId || usedWithItem.itemId !== usedWithItemId) { return; } - player.actionPipeline.call('item_on_item', - player, usedItem, usedSlot, usedWidgetId, usedWithItem, usedWithSlot, usedWithWidgetId); + player.actionPipeline.call('item_on_item', player, usedItem, usedSlot, usedWidgetId, usedWithItem, usedWithSlot, usedWithWidgetId); } else { - logger.warn(`Unhandled item on item case using widgets ${usedWidgetId}:${usedContainerId} => ${usedWithWidgetId}:${usedWithContainerId}`); + logger.warn( + `Unhandled item on item case using widgets ${usedWidgetId}:${usedContainerId} => ${usedWithWidgetId}:${usedWithContainerId}`, + ); } }; export default { opcode: 40, size: 16, - handler: itemOnItemPacket + handler: itemOnItemPacket, }; diff --git a/src/engine/net/inbound-packets/item-on-npc.packet.ts b/src/engine/net/inbound-packets/item-on-npc.packet.ts index a382067df..6432f25a8 100644 --- a/src/engine/net/inbound-packets/item-on-npc.packet.ts +++ b/src/engine/net/inbound-packets/item-on-npc.packet.ts @@ -1,9 +1,9 @@ -import { logger } from '@runejs/common'; -import { activeWorld } from '@engine/world'; +import { widgets } from '@engine/config/config-handler'; import type { PacketData } from '@engine/net/inbound-packet-handler'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import { World } from '@engine/world/world'; +import { logger } from '@runejs/common'; const itemOnNpcPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -15,23 +15,22 @@ const itemOnNpcPacket = (player: Player, packet: PacketData) => { let usedItem; if (itemWidgetId === widgets.inventory.widgetId && itemContainerId === widgets.inventory.containerId) { - if(itemSlot < 0 || itemSlot > 27) { + if (itemSlot < 0 || itemSlot > 27) { return; } usedItem = player.inventory.items[itemSlot]; - if(!usedItem) { + if (!usedItem) { return; } - if(usedItem.itemId !== itemId) { + if (usedItem.itemId !== itemId) { return; } } else { - logger.warn(`Unhandled item on object case using widget ${ itemWidgetId }:${ itemContainerId }`); + logger.warn(`Unhandled item on object case using widget ${itemWidgetId}:${itemContainerId}`); } - if (npcIndex < 0 || npcIndex > World.MAX_NPCS - 1) { return; } @@ -49,11 +48,11 @@ const itemOnNpcPacket = (player: Player, packet: PacketData) => { return; } - player.actionPipeline.call('item_on_npc', player, npc, position, usedItem, itemWidgetId, itemContainerId) + player.actionPipeline.call('item_on_npc', player, npc, position, usedItem, itemWidgetId, itemContainerId); }; export default { opcode: 208, size: 10, - handler: itemOnNpcPacket + handler: itemOnNpcPacket, }; diff --git a/src/engine/net/inbound-packets/item-on-object.packet.ts b/src/engine/net/inbound-packets/item-on-object.packet.ts index 40bb9eca9..4625b9453 100644 --- a/src/engine/net/inbound-packets/item-on-object.packet.ts +++ b/src/engine/net/inbound-packets/item-on-object.packet.ts @@ -1,11 +1,11 @@ -import { logger } from '@runejs/common'; -import { filestore } from '@server/game/game-server'; -import { activeWorld } from '@engine/world'; +import { widgets } from '@engine/config/config-handler'; import type { PacketData } from '@engine/net/inbound-packet-handler'; +import { getVarbitMorphIndex } from '@engine/util/varbits'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; -import { getVarbitMorphIndex } from '@engine/util/varbits'; +import { logger } from '@runejs/common'; +import { filestore } from '@server/game/game-server'; const itemOnObjectPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -39,7 +39,7 @@ const itemOnObjectPacket = (player: Player, packet: PacketData) => { const objectPosition = new Position(objectX, objectY, level); const { object: locationObject, cacheOriginal } = activeWorld.findObjectAtLocation(player, objectId, objectPosition); - if(!locationObject) { + if (!locationObject) { return; } @@ -49,25 +49,37 @@ const itemOnObjectPacket = (player: Player, packet: PacketData) => { logger.error(`Could not find object config for object id ${objectId}!`); } else if (objectConfig.configChangeDest) { let morphIndex = -1; - if(objectConfig.varbitId === -1) { - if(objectConfig.configId !== -1) { - const configValue = player.metadata.configs && player.metadata.configs[objectConfig.configId] ? player.metadata.configs[objectConfig.configId] : 0; + if (objectConfig.varbitId === -1) { + if (objectConfig.configId !== -1) { + const configValue = + player.metadata.configs && player.metadata.configs[objectConfig.configId] + ? player.metadata.configs[objectConfig.configId] + : 0; morphIndex = configValue; - } } else { morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs); } - if(morphIndex !== -1) { + if (morphIndex !== -1) { objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]); } } - player.actionPipeline.call('item_on_object', player, locationObject, objectConfig, objectPosition, usedItem, itemWidgetId, itemContainerId, cacheOriginal); + player.actionPipeline.call( + 'item_on_object', + player, + locationObject, + objectConfig, + objectPosition, + usedItem, + itemWidgetId, + itemContainerId, + cacheOriginal, + ); }; export default { opcode: 24, size: 14, - handler: itemOnObjectPacket + handler: itemOnObjectPacket, }; diff --git a/src/engine/net/inbound-packets/item-on-player.packet.ts b/src/engine/net/inbound-packets/item-on-player.packet.ts index 8b095b60a..9cc9fd40a 100644 --- a/src/engine/net/inbound-packets/item-on-player.packet.ts +++ b/src/engine/net/inbound-packets/item-on-player.packet.ts @@ -1,9 +1,9 @@ -import { logger } from '@runejs/common'; -import { activeWorld } from '@engine/world'; +import { widgets } from '@engine/config/config-handler'; import type { PacketData } from '@engine/net/inbound-packet-handler'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import { World } from '@engine/world/world'; +import { logger } from '@runejs/common'; const itemOnPlayerPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -13,52 +13,46 @@ const itemOnPlayerPacket = (player: Player, packet: PacketData) => { const itemId = buffer.get('short', 'u'); const itemSlot = buffer.get('short', 'u'); - let usedItem; - if(itemWidgetId === widgets.inventory.widgetId && itemContainerId === widgets.inventory.containerId) { - if(itemSlot < 0 || itemSlot > 27) { + if (itemWidgetId === widgets.inventory.widgetId && itemContainerId === widgets.inventory.containerId) { + if (itemSlot < 0 || itemSlot > 27) { return; } usedItem = player.inventory.items[itemSlot]; - if(!usedItem) { + if (!usedItem) { return; } - if(usedItem.itemId !== itemId) { + if (usedItem.itemId !== itemId) { return; } } else { - logger.warn(`Unhandled item on object case using widget ${ itemWidgetId }:${ itemContainerId }`); + logger.warn(`Unhandled item on object case using widget ${itemWidgetId}:${itemContainerId}`); } - - if(playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { + if (playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { return; } const otherPlayer = activeWorld.playerList[playerIndex]; - if(!otherPlayer) { + if (!otherPlayer) { return; } - const position = otherPlayer.position; const distance = Math.floor(position.distanceBetween(player.position)); - - // Too far away - if(distance > 16) { + if (distance > 16) { return; } - - player.actionPipeline.call('item_on_player', player, otherPlayer, position, usedItem, itemWidgetId, itemContainerId) + player.actionPipeline.call('item_on_player', player, otherPlayer, position, usedItem, itemWidgetId, itemContainerId); }; export default { opcode: 110, size: 10, - handler: itemOnPlayerPacket + handler: itemOnPlayerPacket, }; diff --git a/src/engine/net/inbound-packets/item-on-world-item.packet.ts b/src/engine/net/inbound-packets/item-on-world-item.packet.ts index a67f0e861..f3a8fc9ea 100644 --- a/src/engine/net/inbound-packets/item-on-world-item.packet.ts +++ b/src/engine/net/inbound-packets/item-on-world-item.packet.ts @@ -1,8 +1,8 @@ -import { logger } from '@runejs/common'; +import { widgets } from '@engine/config/config-handler'; import type { PacketData } from '@engine/net/inbound-packet-handler'; import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; +import { logger } from '@runejs/common'; /** * Parses the item on world item packet and calls the `item_on_world_item` action pipeline. @@ -28,21 +28,25 @@ const itemOnWorldItemPacket = (player: Player, packet: PacketData) => { const position = new Position(usedWithX, usedWithY, player.position.level); - if(usedWidgetId === widgets.inventory.widgetId && usedContainerId === widgets.inventory.containerId) { + if (usedWidgetId === widgets.inventory.widgetId && usedContainerId === widgets.inventory.containerId) { // TODO (James) we should use constants for these rather than magic numbers - if(usedSlot < 0 || usedSlot > 27) { + if (usedSlot < 0 || usedSlot > 27) { return; } const usedItem = player.inventory.items[usedSlot]; const usedWithItem = player.instance.getTileModifications(position).mods.worldItems.find(p => p.itemId === usedWithItemId); - if(!usedItem || !usedWithItem) { - logger.warn(`Unhandled item on world item case (A) for ${usedSlot} (${usedItemId}) on ${usedWithItemId} (${usedWithX}, ${usedWithY}) by ${player.username}`); + if (!usedItem || !usedWithItem) { + logger.warn( + `Unhandled item on world item case (A) for ${usedSlot} (${usedItemId}) on ${usedWithItemId} (${usedWithX}, ${usedWithY}) by ${player.username}`, + ); return; } - if(usedItem.itemId !== usedItemId || usedWithItem.itemId !== usedWithItemId) { - logger.warn(`Unhandled item on world item case (B) for ${usedItem.itemId}:${usedItemId} on ${usedWithItem.itemId}:${usedWithItemId} by ${player.username}`); + if (usedItem.itemId !== usedItemId || usedWithItem.itemId !== usedWithItemId) { + logger.warn( + `Unhandled item on world item case (B) for ${usedItem.itemId}:${usedItemId} on ${usedWithItem.itemId}:${usedWithItemId} by ${player.username}`, + ); return; } @@ -50,11 +54,10 @@ const itemOnWorldItemPacket = (player: Player, packet: PacketData) => { } else { logger.warn(`Unhandled item on world item case (C) using widgets ${usedWidgetId}:${usedContainerId} by ${player.username}`); } - }; export default { opcode: 172, size: 14, - handler: itemOnWorldItemPacket + handler: itemOnWorldItemPacket, }; diff --git a/src/engine/net/inbound-packets/item-swap.packet.ts b/src/engine/net/inbound-packets/item-swap.packet.ts index 227f1c83a..f7c49ad15 100644 --- a/src/engine/net/inbound-packets/item-swap.packet.ts +++ b/src/engine/net/inbound-packets/item-swap.packet.ts @@ -9,19 +9,19 @@ const itemSwapPacket = (player: Player, packet: PacketData) => { const containerId = buffer.get('short'); const widgetId = buffer.get('short'); - if(toSlot < 0 || fromSlot < 0) { + if (toSlot < 0 || fromSlot < 0) { return; } - if(swapType === 0) { - player.actionPipeline.call('item_swap', player, fromSlot, toSlot, { widgetId, containerId }) - } else if(swapType === 1) { - player.actionPipeline.call('move_item', player, fromSlot, toSlot, { widgetId, containerId }) + if (swapType === 0) { + player.actionPipeline.call('item_swap', player, fromSlot, toSlot, { widgetId, containerId }); + } else if (swapType === 1) { + player.actionPipeline.call('move_item', player, fromSlot, toSlot, { widgetId, containerId }); } }; export default { opcode: 83, size: 9, - handler: itemSwapPacket -} + handler: itemSwapPacket, +}; diff --git a/src/engine/net/inbound-packets/junk.packet.ts b/src/engine/net/inbound-packets/junk.packet.ts index 0788019c8..37baae8ed 100644 --- a/src/engine/net/inbound-packets/junk.packet.ts +++ b/src/engine/net/inbound-packets/junk.packet.ts @@ -4,30 +4,36 @@ export default [ { opcode: 234, size: 4, - handler - }, { + handler, + }, + { opcode: 160, size: 1, - handler - }, { + handler, + }, + { opcode: 216, size: 0, - handler - }, { + handler, + }, + { opcode: 13, size: 0, - handler - }, { + handler, + }, + { opcode: 58, // camera move size: 4, - handler - }, { + handler, + }, + { opcode: 121, size: 4, - handler - }, { + handler, + }, + { opcode: 178, size: 0, - handler - } + handler, + }, ]; diff --git a/src/engine/net/inbound-packets/magic-attack.packet.ts b/src/engine/net/inbound-packets/magic-attack.packet.ts index 1a4dc9176..7e7c07b9d 100644 --- a/src/engine/net/inbound-packets/magic-attack.packet.ts +++ b/src/engine/net/inbound-packets/magic-attack.packet.ts @@ -1,7 +1,6 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; -import type { Player } from '@engine/world/actor/player/player'; import { activeWorld } from '@engine/world'; - +import type { Player } from '@engine/world/actor/player/player'; const magicAttackPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -14,8 +13,10 @@ const magicAttackPacket = (player: Player, packet: PacketData) => { player.actionPipeline.call('magic_on_npc', npc, player, widgetId, widgetChildId); }; -export default [{ - opcode: 253, - size: 6, - handler: magicAttackPacket -}]; +export default [ + { + opcode: 253, + size: 6, + handler: magicAttackPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/npc-interaction.packet.ts b/src/engine/net/inbound-packets/npc-interaction.packet.ts index 8a0b7df41..69d261410 100644 --- a/src/engine/net/inbound-packets/npc-interaction.packet.ts +++ b/src/engine/net/inbound-packets/npc-interaction.packet.ts @@ -1,8 +1,8 @@ -import { logger } from '@runejs/common'; import type { PacketData } from '@engine/net/inbound-packet-handler'; -import type { Player } from '@engine/world/actor/player/player'; import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; import { World } from '@engine/world/world'; +import { logger } from '@runejs/common'; const npcInteractionPacket = (player: Player, packet: PacketData) => { const { buffer, packetId } = packet; @@ -46,8 +46,8 @@ const npcInteractionPacket = (player: Player, packet: PacketData) => { const actionIdx = actions[packetId]; let optionName = `action-${actionIdx + 1}`; - if(options && options.length >= actionIdx) { - if(!options[actionIdx] || options[actionIdx].toLowerCase() === 'hidden') { + if (options && options.length >= actionIdx) { + if (!options[actionIdx] || options[actionIdx].toLowerCase() === 'hidden') { // Invalid action logger.info(npc); logger.error(`1: Invalid npc ${morphedNpc?.gameId || npc.id} option ${actionIdx + 1}, options: ${JSON.stringify(options)}`); @@ -70,16 +70,20 @@ const npcInteractionPacket = (player: Player, packet: PacketData) => { player.actionPipeline.call('npc_interaction', player, npc, position, optionName.toLowerCase()); }; -export default [{ - opcode: 63, - size: 2, - handler: npcInteractionPacket -}, { - opcode: 116, - size: 2, - handler: npcInteractionPacket -}, { - opcode: 57, - size: 2, - handler: npcInteractionPacket -}]; +export default [ + { + opcode: 63, + size: 2, + handler: npcInteractionPacket, + }, + { + opcode: 116, + size: 2, + handler: npcInteractionPacket, + }, + { + opcode: 57, + size: 2, + handler: npcInteractionPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/number-input.packet.ts b/src/engine/net/inbound-packets/number-input.packet.ts index 44fc280cb..a83203ba8 100644 --- a/src/engine/net/inbound-packets/number-input.packet.ts +++ b/src/engine/net/inbound-packets/number-input.packet.ts @@ -4,6 +4,5 @@ import type { Player } from '@engine/world/actor/player/player'; export default { opcode: 238, size: 4, - handler: (player: Player, packet: PacketData) => - player.numericInputEvent.next(packet.buffer.get('int', 'u')) + handler: (player: Player, packet: PacketData) => player.numericInputEvent.next(packet.buffer.get('int', 'u')), }; diff --git a/src/engine/net/inbound-packets/object-interaction.packet.ts b/src/engine/net/inbound-packets/object-interaction.packet.ts index 94838acaa..29d48df73 100644 --- a/src/engine/net/inbound-packets/object-interaction.packet.ts +++ b/src/engine/net/inbound-packets/object-interaction.packet.ts @@ -7,7 +7,6 @@ import { Position } from '@engine/world/position'; import { logger } from '@runejs/common'; import { filestore } from '@server/game/game-server'; - interface ObjectInteractionData { objectId: number; x: number; @@ -16,7 +15,6 @@ interface ObjectInteractionData { type objectInteractionPacket = (packet: PacketData) => ObjectInteractionData; - const option1: objectInteractionPacket = packet => { const { buffer } = packet; const objectId = buffer.get('short', 'u'); @@ -57,16 +55,14 @@ const option5: objectInteractionPacket = packet => { return { objectId, x, y }; }; - -const objectInteractionPackets: { [key: number]: { packetDef: objectInteractionPacket, index: number } } = { - 30: { packetDef: option1, index: 0 }, +const objectInteractionPackets: { [key: number]: { packetDef: objectInteractionPacket; index: number } } = { + 30: { packetDef: option1, index: 0 }, 164: { packetDef: option2, index: 1 }, 183: { packetDef: option3, index: 2 }, 229: { packetDef: option4, index: 3 }, - 62: { packetDef: option5, index: 4 }, + 62: { packetDef: option5, index: 4 }, }; - const objectInteractionPacket = (player: Player, packet: PacketData) => { const { packetId } = packet; @@ -74,8 +70,8 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { const level = player.position.level; const objectPosition = new Position(x, y, level); const { object: landscapeObject, cacheOriginal } = activeWorld.findObjectAtLocation(player, objectId, objectPosition); - if(!landscapeObject) { - if(player.rights === Rights.ADMIN) { + if (!landscapeObject) { + if (player.rights === Rights.ADMIN) { player.sendMessage(`Custom object ${objectId} @[${objectPosition.key}]`); } return; @@ -90,15 +86,17 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { if (objectConfig.configChangeDest) { let morphIndex = -1; - if(objectConfig.varbitId === -1) { - if(objectConfig.configId !== -1) { - morphIndex = player.metadata.configs && player.metadata.configs[objectConfig.configId] ? - player.metadata.configs[objectConfig.configId] : 0; + if (objectConfig.varbitId === -1) { + if (objectConfig.configId !== -1) { + morphIndex = + player.metadata.configs && player.metadata.configs[objectConfig.configId] + ? player.metadata.configs[objectConfig.configId] + : 0; } } else { morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs); } - if(morphIndex !== -1) { + if (morphIndex !== -1) { objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]); } } @@ -110,8 +108,8 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { const actionIdx = objectInteractionPackets[packetId].index; let optionName = `action-${actionIdx + 1}`; - if(objectConfig.options && objectConfig.options.length >= actionIdx) { - if(!objectConfig.options[actionIdx]) { + if (objectConfig.options && objectConfig.options.length >= actionIdx) { + if (!objectConfig.options[actionIdx]) { // Invalid action logger.error(`1: Invalid object ${objectId} option ${actionIdx + 1}, options: ${JSON.stringify(objectConfig.options)}`); return; @@ -124,12 +122,19 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { return; } - player.actionPipeline.call('object_interaction', player, landscapeObject, objectConfig, objectPosition, optionName.toLowerCase(), cacheOriginal); + player.actionPipeline.call( + 'object_interaction', + player, + landscapeObject, + objectConfig, + objectPosition, + optionName.toLowerCase(), + cacheOriginal, + ); }; - export default Object.keys(objectInteractionPackets).map(opcode => ({ opcode: parseInt(opcode, 10), size: 6, - handler: objectInteractionPacket + handler: objectInteractionPacket, })); diff --git a/src/engine/net/inbound-packets/pickup-item.packet.ts b/src/engine/net/inbound-packets/pickup-item.packet.ts index 4cdc17edb..0853e7d40 100644 --- a/src/engine/net/inbound-packets/pickup-item.packet.ts +++ b/src/engine/net/inbound-packets/pickup-item.packet.ts @@ -16,14 +16,14 @@ const pickupItemPacket = (player: Player, packet: PacketData) => { let worldItem = worldItems.find(i => i.itemId === itemId) || null; - if(!worldItem) { + if (!worldItem) { const personalMods = player.personalInstance.getInstancedChunk(worldItemPosition); const personalItems = personalMods?.mods?.get(worldItemPosition.key)?.worldItems || []; worldItem = personalItems.find(i => i.itemId === itemId) || null; } - if(worldItem && !worldItem.removed) { - if(worldItem.owner && !worldItem.owner.equals(player)) { + if (worldItem && !worldItem.removed) { + if (worldItem.owner && !worldItem.owner.equals(player)) { return; } @@ -34,5 +34,5 @@ const pickupItemPacket = (player: Player, packet: PacketData) => { export default { opcode: 85, size: 6, - handler: pickupItemPacket + handler: pickupItemPacket, }; diff --git a/src/engine/net/inbound-packets/player-interaction.packet.ts b/src/engine/net/inbound-packets/player-interaction.packet.ts index 0c4b6c854..5dfb27b8c 100644 --- a/src/engine/net/inbound-packets/player-interaction.packet.ts +++ b/src/engine/net/inbound-packets/player-interaction.packet.ts @@ -1,8 +1,8 @@ -import { logger } from '@runejs/common'; import type { PacketData } from '@engine/net/inbound-packet-handler'; -import { playerOptions, type Player } from '@engine/world/actor/player/player'; import { activeWorld } from '@engine/world'; +import { type Player, playerOptions } from '@engine/world/actor/player/player'; import { World } from '@engine/world/world'; +import { logger } from '@runejs/common'; const playerInteractionPacket = (player: Player, packet: PacketData) => { const { buffer, packetId } = packet; @@ -14,12 +14,12 @@ const playerInteractionPacket = (player: Player, packet: PacketData) => { const playerIndex = packetReaders[packetId]() - 1; - if(playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { + if (playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { return; } const otherPlayer = activeWorld.playerList[playerIndex]; - if(!otherPlayer) { + if (!otherPlayer) { return; } @@ -27,18 +27,18 @@ const playerInteractionPacket = (player: Player, packet: PacketData) => { const distance = Math.floor(position.distanceBetween(player.position)); // Too far away - if(distance > 16) { + if (distance > 16) { return; } const actions = { 68: 0, - 211: 1 + 211: 1, }; const playerOption = playerOptions.find(playerOption => playerOption.index === actions[packetId]); - if(!playerOption) { + if (!playerOption) { logger.error(`Invalid player option ${actions[packetId]}!`); return; } @@ -46,12 +46,15 @@ const playerInteractionPacket = (player: Player, packet: PacketData) => { player.actionPipeline.call('player_interaction', player, otherPlayer, position, playerOption.option.toLowerCase()); }; -export default [{ - opcode: 68, - size: 2, - handler: playerInteractionPacket -}, { - opcode: 211, - size: 2, - handler: playerInteractionPacket -}]; +export default [ + { + opcode: 68, + size: 2, + handler: playerInteractionPacket, + }, + { + opcode: 211, + size: 2, + handler: playerInteractionPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/private-message.packet.ts b/src/engine/net/inbound-packets/private-message.packet.ts index e8fe14769..71d23d0b6 100644 --- a/src/engine/net/inbound-packets/private-message.packet.ts +++ b/src/engine/net/inbound-packets/private-message.packet.ts @@ -1,7 +1,7 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; -import type { Player } from '@engine/world/actor/player/player'; -import { activeWorld } from '@engine/world'; import { longToString } from '@engine/util/strings'; +import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; export default { opcode: 207, @@ -14,13 +14,13 @@ export default { const username = longToString(nameLong).toLowerCase(); const messageLength = buffer.length - 9; const messageBytes = new Array(messageLength); - for(let i = 0; i < messageLength; i++) { + for (let i = 0; i < messageLength; i++) { messageBytes[i] = buffer[buffer.readerIndex + i]; } const otherPlayer = activeWorld.findActivePlayerByUsername(username); - if(otherPlayer) { + if (otherPlayer) { otherPlayer.privateMessageReceived(player, messageBytes); } - } + }, }; diff --git a/src/engine/net/inbound-packets/remove-friend.packet.ts b/src/engine/net/inbound-packets/remove-friend.packet.ts index 5e6551e7b..8ea324ae2 100644 --- a/src/engine/net/inbound-packets/remove-friend.packet.ts +++ b/src/engine/net/inbound-packets/remove-friend.packet.ts @@ -8,11 +8,11 @@ export default { size: 8, handler: (player: Player, packet: PacketData) => { const friendName = longToString(BigInt(packet.buffer.get('long'))); - if(!friendName) { + if (!friendName) { return; } player.removeFriend(friendName); PrivateMessaging.friendRemoved(player, friendName); - } + }, }; diff --git a/src/engine/net/inbound-packets/remove-ignore.packet.ts b/src/engine/net/inbound-packets/remove-ignore.packet.ts index aadabd634..2576c13b2 100644 --- a/src/engine/net/inbound-packets/remove-ignore.packet.ts +++ b/src/engine/net/inbound-packets/remove-ignore.packet.ts @@ -5,6 +5,5 @@ import type { Player } from '@engine/world/actor/player/player'; export default { opcode: 28, size: 8, - handler: (player: Player, packet: PacketData) => - player.removeIgnoredPlayer(longToString(BigInt(packet.buffer.get('long')))) + handler: (player: Player, packet: PacketData) => player.removeIgnoredPlayer(longToString(BigInt(packet.buffer.get('long')))), }; diff --git a/src/engine/net/inbound-packets/social-button.packet.ts b/src/engine/net/inbound-packets/social-button.packet.ts index 28ed3e381..8c55c1a70 100644 --- a/src/engine/net/inbound-packets/social-button.packet.ts +++ b/src/engine/net/inbound-packets/social-button.packet.ts @@ -14,8 +14,8 @@ export default { player.settings.privateChatMode = buffer.get('byte'); player.settings.tradeMode = buffer.get('byte'); - if(currentPrivateChatMode !== player.settings.privateChatMode) { + if (currentPrivateChatMode !== player.settings.privateChatMode) { PrivateMessaging.playerPrivateChatModeChanged(player); } - } + }, }; diff --git a/src/engine/net/inbound-packets/walk.packet.ts b/src/engine/net/inbound-packets/walk.packet.ts index 41cee22ad..35a17ff04 100644 --- a/src/engine/net/inbound-packets/walk.packet.ts +++ b/src/engine/net/inbound-packets/walk.packet.ts @@ -5,7 +5,7 @@ const walkPacket = (player: Player, packet: PacketData) => { const { buffer, packetSize, packetId } = packet; let size = packetSize; - if(packetId === 236) { + if (packetId === 236) { size -= 14; } @@ -27,23 +27,27 @@ const walkPacket = (player: Player, packet: PacketData) => { walkingQueue.valid = true; walkingQueue.add(firstX, firstY); - for(let i = 0; i < totalSteps; i++) { + for (let i = 0; i < totalSteps; i++) { const x = buffer.get('byte'); const y = buffer.get('byte'); walkingQueue.add(x + firstX, y + firstY); } }; -export default [{ - opcode: 73, - size: -1, - handler: walkPacket -}, { - opcode: 236, - size: -1, - handler: walkPacket -}, { - opcode: 89, - size: -1, - handler: walkPacket -}]; +export default [ + { + opcode: 73, + size: -1, + handler: walkPacket, + }, + { + opcode: 236, + size: -1, + handler: walkPacket, + }, + { + opcode: 89, + size: -1, + handler: walkPacket, + }, +]; diff --git a/src/engine/net/inbound-packets/widget-interaction.packet.ts b/src/engine/net/inbound-packets/widget-interaction.packet.ts index 9857b502e..440641aaf 100644 --- a/src/engine/net/inbound-packets/widget-interaction.packet.ts +++ b/src/engine/net/inbound-packets/widget-interaction.packet.ts @@ -1,7 +1,6 @@ import type { PacketData } from '@engine/net/inbound-packet-handler'; import type { Player } from '@engine/world/actor/player/player'; - const widgetInteractionPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const childId = buffer.get('short'); @@ -14,5 +13,5 @@ const widgetInteractionPacket = (player: Player, packet: PacketData) => { export default { opcode: 132, size: 6, - handler: widgetInteractionPacket + handler: widgetInteractionPacket, }; diff --git a/src/engine/net/inbound-packets/widgets-closed.packet.ts b/src/engine/net/inbound-packets/widgets-closed.packet.ts index 61ceb792b..9c7d7a0d0 100644 --- a/src/engine/net/inbound-packets/widgets-closed.packet.ts +++ b/src/engine/net/inbound-packets/widgets-closed.packet.ts @@ -1,5 +1,5 @@ export default { opcode: 176, size: 0, - handler: player => player.interfaceState.closeAllSlots() + handler: player => player.interfaceState.closeAllSlots(), }; diff --git a/src/engine/net/isaac.ts b/src/engine/net/isaac.ts index df9cd0dc1..c0467d45f 100644 --- a/src/engine/net/isaac.ts +++ b/src/engine/net/isaac.ts @@ -1,5 +1,4 @@ export class Isaac { - private m: number[] = Array(256); // internal memory private acc = 0; // accumulator private brs = 0; // last result @@ -17,14 +16,13 @@ export class Isaac { public add(x: number, y: number): number { const lsb = (x & 0xffff) + (y & 0xffff); - const msb = (x >>> 16) + (y >>> 16) + (lsb >>> 16); + const msb = (x >>> 16) + (y >>> 16) + (lsb >>> 16); return (msb << 16) | (lsb & 0xffff); } public reset(): void { this.acc = this.brs = this.cnt = 0; - for(let i = 0; i < 256; ++i) - this.m[i] = this.r[i] = 0; + for (let i = 0; i < 256; ++i) this.m[i] = this.r[i] = 0; this.gnt = 0; } @@ -32,90 +30,133 @@ export class Isaac { let a, b, c, d, e, f, g, h, i; /* seeding the seeds of love */ - a = b = c = d = - e = f = g = h = 0x9e3779b9; /* the golden ratio */ + a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */ this.reset(); - for(i = 0; i < s.length; i++) - this.r[i & 0xff] += (typeof(s[i]) === 'number') ? s[i] : 0; + for (i = 0; i < s.length; i++) this.r[i & 0xff] += typeof s[i] === 'number' ? s[i] : 0; /* private: seed mixer */ const seed_mix = () => { - a ^= b << 11; d = this.add(d, a); b = this.add(b, c); - b ^= c >>> 2; e = this.add(e, b); c = this.add(c, d); - c ^= d << 8; f = this.add(f, c); d = this.add(d, e); - d ^= e >>> 16; g = this.add(g, d); e = this.add(e, f); - e ^= f << 10; h = this.add(h, e); f = this.add(f, g); - f ^= g >>> 4; a = this.add(a, f); g = this.add(g, h); - g ^= h << 8; b = this.add(b, g); h = this.add(h, a); - h ^= a >>> 9; c = this.add(c, h); a = this.add(a, b); + a ^= b << 11; + d = this.add(d, a); + b = this.add(b, c); + b ^= c >>> 2; + e = this.add(e, b); + c = this.add(c, d); + c ^= d << 8; + f = this.add(f, c); + d = this.add(d, e); + d ^= e >>> 16; + g = this.add(g, d); + e = this.add(e, f); + e ^= f << 10; + h = this.add(h, e); + f = this.add(f, g); + f ^= g >>> 4; + a = this.add(a, f); + g = this.add(g, h); + g ^= h << 8; + b = this.add(b, g); + h = this.add(h, a); + h ^= a >>> 9; + c = this.add(c, h); + a = this.add(a, b); }; - for(i = 0; i < 4; i++) /* scramble it */ - seed_mix(); - - for(i = 0; i < 256; i += 8) { - if(s) { /* use all the information in the seed */ - a = this.add(a, this.r[i + 0]); b = this.add(b, this.r[i + 1]); - c = this.add(c, this.r[i + 2]); d = this.add(d, this.r[i + 3]); - e = this.add(e, this.r[i + 4]); f = this.add(f, this.r[i + 5]); - g = this.add(g, this.r[i + 6]); h = this.add(h, this.r[i + 7]); + for (i = 0; i < 4; i++ /* scramble it */) seed_mix(); + + for (i = 0; i < 256; i += 8) { + if (s) { + /* use all the information in the seed */ + a = this.add(a, this.r[i + 0]); + b = this.add(b, this.r[i + 1]); + c = this.add(c, this.r[i + 2]); + d = this.add(d, this.r[i + 3]); + e = this.add(e, this.r[i + 4]); + f = this.add(f, this.r[i + 5]); + g = this.add(g, this.r[i + 6]); + h = this.add(h, this.r[i + 7]); } seed_mix(); /* fill in m[] with messy stuff */ - this.m[i + 0] = a; this.m[i + 1] = b; this.m[i + 2] = c; this.m[i + 3] = d; - this.m[i + 4] = e; this.m[i + 5] = f; this.m[i + 6] = g; this.m[i + 7] = h; + this.m[i + 0] = a; + this.m[i + 1] = b; + this.m[i + 2] = c; + this.m[i + 3] = d; + this.m[i + 4] = e; + this.m[i + 5] = f; + this.m[i + 6] = g; + this.m[i + 7] = h; } - if(s) { + if (s) { /* do a second pass to make all of the seed affect all of m[] */ - for(i = 0; i < 256; i += 8) { - a = this.add(a, this.m[i + 0]); b = this.add(b, this.m[i + 1]); - c = this.add(c, this.m[i + 2]); d = this.add(d, this.m[i + 3]); - e = this.add(e, this.m[i + 4]); f = this.add(f, this.m[i + 5]); - g = this.add(g, this.m[i + 6]); h = this.add(h, this.m[i + 7]); + for (i = 0; i < 256; i += 8) { + a = this.add(a, this.m[i + 0]); + b = this.add(b, this.m[i + 1]); + c = this.add(c, this.m[i + 2]); + d = this.add(d, this.m[i + 3]); + e = this.add(e, this.m[i + 4]); + f = this.add(f, this.m[i + 5]); + g = this.add(g, this.m[i + 6]); + h = this.add(h, this.m[i + 7]); seed_mix(); /* fill in m[] with messy stuff (again) */ - this.m[i + 0] = a; this.m[i + 1] = b; this.m[i + 2] = c; this.m[i + 3] = d; - this.m[i + 4] = e; this.m[i + 5] = f; this.m[i + 6] = g; this.m[i + 7] = h; + this.m[i + 0] = a; + this.m[i + 1] = b; + this.m[i + 2] = c; + this.m[i + 3] = d; + this.m[i + 4] = e; + this.m[i + 5] = f; + this.m[i + 6] = g; + this.m[i + 7] = h; } } this.prng(); /* fill in the first set of results */ - this.gnt = 256; /* prepare to use the first set of results */ + this.gnt = 256; /* prepare to use the first set of results */ } public prng(n?: number): void { let i, x, y; - n = (n && typeof(n) === 'number') - ? Math.abs(Math.floor(n)) : 1; + n = n && typeof n === 'number' ? Math.abs(Math.floor(n)) : 1; - while(n--) { - this.cnt = this.add(this.cnt, 1); + while (n--) { + this.cnt = this.add(this.cnt, 1); this.brs = this.add(this.brs, this.cnt); - for(i = 0; i < 256; i++) { - switch(i & 3) { - case 0: this.acc ^= this.acc << 13; break; - case 1: this.acc ^= this.acc >>> 6; break; - case 2: this.acc ^= this.acc << 2; break; - case 3: this.acc ^= this.acc >>> 16; break; + for (i = 0; i < 256; i++) { + switch (i & 3) { + case 0: + this.acc ^= this.acc << 13; + break; + case 1: + this.acc ^= this.acc >>> 6; + break; + case 2: + this.acc ^= this.acc << 2; + break; + case 3: + this.acc ^= this.acc >>> 16; + break; } - this.acc = this.add(this.m[(i + 128) & 0xff], this.acc); x = this.m[i]; - this.m[i] = y = this.add(this.m[(x >>> 2) & 0xff], this.add(this.acc, this.brs)); + this.acc = this.add(this.m[(i + 128) & 0xff], this.acc); + x = this.m[i]; + this.m[i] = y = this.add(this.m[(x >>> 2) & 0xff], this.add(this.acc, this.brs)); this.r[i] = this.brs = this.add(this.m[(y >>> 10) & 0xff], x); } } } public rand(): number { - if(!this.gnt--) { - this.prng(); this.gnt = 255; + if (!this.gnt--) { + this.prng(); + this.gnt = 255; } return this.r[this.gnt]; } - public internals(): { a: number, b: number, c: number, m: number[], r: number[] } { + public internals(): { a: number; b: number; c: number; m: number[]; r: number[] } { return { a: this.acc, b: this.brs, c: this.cnt, m: this.m, r: this.r }; } } diff --git a/src/engine/net/outbound-packet-handler.ts b/src/engine/net/outbound-packet-handler.ts index 766a92e29..2d31eca74 100644 --- a/src/engine/net/outbound-packet-handler.ts +++ b/src/engine/net/outbound-packet-handler.ts @@ -1,25 +1,24 @@ import type { Socket } from 'net'; -import type { LandscapeObject } from '@runejs/filestore'; -import { ByteBuffer, logger } from '@runejs/common'; -import { activeWorld } from '@engine/world'; import { xteaRegions } from '@engine/config/config-handler'; import { Packet, PacketType } from '@engine/net/packet'; import { stringToLong } from '@engine/util/strings'; +import { activeWorld } from '@engine/world'; import type { Npc } from '@engine/world/actor/npc'; import type { Player, SidebarTab } from '@engine/world/actor/player/player'; import type { Item } from '@engine/world/items/item'; import { ItemContainer } from '@engine/world/items/item-container'; import type { WorldItem } from '@engine/world/items/world-item'; import type { Chunk, ChunkUpdateItem } from '@engine/world/map/chunk'; -import type { ConstructedRegion, ConstructedChunk } from '@engine/world/map/region'; +import type { ConstructedChunk, ConstructedRegion } from '@engine/world/map/region'; import { Position } from '@engine/world/position'; +import { ByteBuffer, logger } from '@runejs/common'; +import type { LandscapeObject } from '@runejs/filestore'; import { serverConfig } from '@server/game/game-server'; /** * A helper class for sending various network packets back to the game client. */ export class OutboundPacketHandler { - private static privateMessageCounter: number = Math.floor(Math.random() * 100000000); private readonly player: Player; @@ -70,7 +69,17 @@ export class OutboundPacketHandler { //packet - 129 - freezes client? //packet - 202 - directly to login screen - public sendProjectile(position: Position, offsetX: number, offsetY: number, id: number, startHeight: number, endHeight: number, speed: number, lockon: number, delay: number) { + public sendProjectile( + position: Position, + offsetX: number, + offsetY: number, + id: number, + startHeight: number, + endHeight: number, + speed: number, + lockon: number, + delay: number, + ) { this.updateReferencePosition(position); const packet = new Packet(1); @@ -125,7 +134,14 @@ export class OutboundPacketHandler { this.queue(packet); } - public playSoundAtPosition(soundId: number, soundX: number, soundY: number, volume: number, radius: number = 5, delay: number = 0): void { + public playSoundAtPosition( + soundId: number, + soundX: number, + soundY: number, + volume: number, + radius: number = 5, + delay: number = 0, + ): void { const packet = new Packet(9); const offset = 0; packet.put(offset, 'BYTE'); @@ -144,21 +160,21 @@ export class OutboundPacketHandler { packet.put(offsetY); chunkUpdates.forEach(update => { - if(update.type === 'ADD') { - if(update.object && !update.object.reference) { + if (update.type === 'ADD') { + if (update.object && !update.object.reference) { const offset = this.getChunkPositionOffset(update.object.x, update.object.y, chunk); packet.put(241, 'BYTE'); packet.put((update.object.type << 2) + (update.object.orientation & 3)); packet.put(update.object.objectId, 'SHORT'); packet.put(offset); - } else if(update.worldItem) { + } else if (update.worldItem) { const offset = this.getChunkPositionOffset(update.worldItem.position.x, update.worldItem.position.y, chunk); packet.put(175, 'BYTE'); packet.put(update.worldItem.itemId, 'SHORT', 'LITTLE_ENDIAN'); packet.put(update.worldItem.amount, 'SHORT'); packet.put(offset, 'BYTE'); } - } else if(update.type === 'REMOVE') { + } else if (update.type === 'REMOVE') { if (!update.object) { logger.warn('Tried to remove object that does not exist.'); return; @@ -227,8 +243,8 @@ export class OutboundPacketHandler { } public updateReferencePosition(position: Position): void { - const offsetX = position.x - (this.player.lastMapRegionUpdatePosition.chunkX * 8); - const offsetY = position.y - (this.player.lastMapRegionUpdatePosition.chunkY * 8); + const offsetX = position.x - this.player.lastMapRegionUpdatePosition.chunkX * 8; + const offsetY = position.y - this.player.lastMapRegionUpdatePosition.chunkY * 8; const packet = new Packet(254); packet.put(offsetY); @@ -250,14 +266,14 @@ export class OutboundPacketHandler { public setWidgetNpcHead(widgetId: number, childId: number, modelId: number): void { const packet = new Packet(160); packet.put(modelId, 'SHORT', 'LITTLE_ENDIAN'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } public setWidgetPlayerHead(widgetId: number, childId: number): void { const packet = new Packet(210); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } @@ -265,7 +281,7 @@ export class OutboundPacketHandler { public playWidgetAnimation(widgetId: number, childId: number, animationId: number): void { const packet = new Packet(24); packet.put(animationId, 'SHORT'); - packet.put(widgetId << 16 | childId, 'INT'); + packet.put((widgetId << 16) | childId, 'INT'); this.queue(packet); } @@ -285,12 +301,12 @@ export class OutboundPacketHandler { public updateClientConfig(configId: number, value: number): void { let packet: Packet; const metadata = this.player.metadata; - if(!metadata.configs) { - metadata.configs = [] + if (!metadata.configs) { + metadata.configs = []; } metadata.configs[configId] = value; - if(value > 128) { + if (value > 128) { packet = new Packet(2); packet.put(value, 'INT'); packet.put(configId, 'SHORT'); @@ -308,7 +324,7 @@ export class OutboundPacketHandler { packet.put(rotationX, 'SHORT'); packet.put(zoom, 'SHORT', 'LITTLE_ENDIAN'); packet.put(rotationY, 'SHORT'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } @@ -316,7 +332,7 @@ export class OutboundPacketHandler { public updateWidgetModel1(widgetId: number, childId: number, modelId: number): void { const packet = new Packet(250); packet.put(modelId, 'SHORT', 'LITTLE_ENDIAN'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } @@ -334,7 +350,7 @@ export class OutboundPacketHandler { public updateWidgetString(widgetId: number, childId: number, value: string): void { const packet = new Packet(110, PacketType.DYNAMIC_LARGE); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); packet.putString(value); this.queue(packet); @@ -343,7 +359,7 @@ export class OutboundPacketHandler { public updateWidgetColor(widgetId: number, childId: number, color: number): void { const packet = new Packet(231); packet.put(color, 'SHORT'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } @@ -365,17 +381,17 @@ export class OutboundPacketHandler { } // @TODO this can support multiple items/slots !!! - public sendUpdateSingleWidgetItem(widget: { widgetId: number, containerId: number }, slot: number, item: Item | null): void { + public sendUpdateSingleWidgetItem(widget: { widgetId: number; containerId: number }, slot: number, item: Item | null): void { const packet = new Packet(214, PacketType.DYNAMIC_LARGE); - packet.put(widget.widgetId << 16 | widget.containerId, 'INT'); + packet.put((widget.widgetId << 16) | widget.containerId, 'INT'); packet.put(slot, 'SMART_SHORT'); - if(!item) { + if (!item) { packet.put(0, 'SHORT'); } else { packet.put(item.itemId + 1, 'SHORT'); // +1 because 0 means an empty slot - if(item.amount >= 255) { + if (item.amount >= 255) { packet.put(255, 'BYTE'); packet.put(item.amount, 'INT'); } else { @@ -386,8 +402,8 @@ export class OutboundPacketHandler { this.queue(packet); } - public update(packet: Packet, widget: { widgetId: number, containerId: number }, container: ItemContainer): void { - const packed = widget.widgetId << 16 | widget.containerId; + public update(packet: Packet, widget: { widgetId: number; containerId: number }, container: ItemContainer): void { + const packed = (widget.widgetId << 16) | widget.containerId; packet.put(packed, 'INT'); const size = container.size; @@ -413,12 +429,12 @@ export class OutboundPacketHandler { this.queue(packet); } - public sendUpdateAllWidgetItems(widget: { widgetId: number, containerId: number }, container: ItemContainer): void { + public sendUpdateAllWidgetItems(widget: { widgetId: number; containerId: number }, container: ItemContainer): void { const packet = new Packet(12, PacketType.DYNAMIC_LARGE); this.update(packet, widget, container); } - public sendUpdateAllWidgetItemsById(widget: { widgetId: number, containerId: number }, itemIds: number[]): void { + public sendUpdateAllWidgetItemsById(widget: { widgetId: number; containerId: number }, itemIds: number[]): void { const container = new ItemContainer(itemIds.length); const items = itemIds.map(id => (!id ? null : { itemId: id, amount: 1 })); container.setAll(items, false); @@ -430,7 +446,7 @@ export class OutboundPacketHandler { const packet = new Packet(120); packet.put(zoom, 'SHORT'); packet.put(itemId, 'SHORT', 'LITTLE_ENDIAN'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } @@ -438,14 +454,14 @@ export class OutboundPacketHandler { public toggleWidgetVisibility(widgetId: number, childId: number, hidden: boolean): void { const packet = new Packet(115); packet.put(hidden ? 1 : 0, 'BYTE'); - packet.put(widgetId << 16 | childId, 'INT', 'LITTLE_ENDIAN'); + packet.put((widgetId << 16) | childId, 'INT', 'LITTLE_ENDIAN'); this.queue(packet); } public moveWidgetChild(widgetId: number, childId: number, offsetX: number, offsetY: number): void { const packet = new Packet(3); - packet.put(widgetId << 16 | childId, 'INT'); + packet.put((widgetId << 16) | childId, 'INT'); packet.put(offsetY, 'SHORT', 'LITTLE_ENDIAN'); packet.put(offsetX, 'SHORT', 'LITTLE_ENDIAN'); @@ -603,7 +619,9 @@ export class OutboundPacketHandler { const mapWorldX = mapData.renderPosition.x; const mapWorldY = mapData.renderPosition.y; - const topCornerMapChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(mapWorldX, mapWorldY, this.player.position.level)); + const topCornerMapChunk = activeWorld.chunkManager.getChunkForWorldPosition( + new Position(mapWorldX, mapWorldY, this.player.position.level), + ); const playerChunk = activeWorld.chunkManager.getChunkForWorldPosition(this.player.position); const offsetX = playerChunk.position.x - (topCornerMapChunk.position.x - 2); @@ -612,26 +630,26 @@ export class OutboundPacketHandler { mapData.drawOffsetX = offsetX - 6; // 6 === center mapData.drawOffsetY = offsetY - 6; // 6 === center - for(let level = 0; level < 4; level++) { - for(let x = 0; x < 13; x++) { - for(let y = 0; y < 13; y++) { + for (let level = 0; level < 4; level++) { + for (let x = 0; x < 13; x++) { + for (let y = 0; y < 13; y++) { let mapTileOffsetX = x + mapData.drawOffsetX; let mapTileOffsetY = y + mapData.drawOffsetY; - if(mapTileOffsetX < 0) { + if (mapTileOffsetX < 0) { mapTileOffsetX = 0; } - if(mapTileOffsetX > 12) { + if (mapTileOffsetX > 12) { mapTileOffsetX = 12; } - if(mapTileOffsetY < 0) { + if (mapTileOffsetY < 0) { mapTileOffsetY = 0; } - if(mapTileOffsetY > 12) { + if (mapTileOffsetY > 12) { mapTileOffsetY = 12; } const constructedChunk: ConstructedChunk | null = mapData.chunks[level][mapTileOffsetX][mapTileOffsetY]; - packet.putBits(1, constructedChunk === null ? 0 : 1) + packet.putBits(1, constructedChunk === null ? 0 : 1); if (constructedChunk !== null) { const { templatePosition, orientation } = constructedChunk; packet.putBits(2, templatePosition?.level & 0x3); @@ -650,9 +668,9 @@ export class OutboundPacketHandler { // Put the xtea keys for the two construction room template maps // Map coords: 29,79 && 30,79 - for(let mapX = 29; mapX <= 30; mapX++) { + for (let mapX = 29; mapX <= 30; mapX++) { const xteaRegion = xteaRegions[`l${mapX}_79`]; - for(let seeds = 0; seeds < 4; seeds++) { + for (let seeds = 0; seeds < 4; seeds++) { packet.put(encryptionEnabled ? (xteaRegion?.key[seeds] ?? 0) : 0, 'int'); } } @@ -675,10 +693,10 @@ export class OutboundPacketHandler { const encryptionEnabled = serverConfig.encryptionEnabled === undefined ? true : serverConfig.encryptionEnabled; - for(let mapX = startX; mapX <= endX; mapX++) { - for(let mapY = startY; mapY <= endY; mapY++) { + for (let mapX = startX; mapX <= endX; mapX++) { + for (let mapY = startY; mapY <= endY; mapY++) { const xteaRegion = xteaRegions[`l${mapX}_${mapY}`]; - for(let seeds = 0; seeds < 4; seeds++) { + for (let seeds = 0; seeds < 4; seeds++) { packet.put(encryptionEnabled ? (xteaRegion?.key[seeds] ?? 0) : 0, 'int'); } } @@ -697,12 +715,12 @@ export class OutboundPacketHandler { } public flushQueue(): void { - if(!this.socket || this.socket.destroyed) { + if (!this.socket || this.socket.destroyed) { return; } const buffer = Buffer.concat([...this.packetQueue, ...this.updatingQueue]); - if(buffer.length !== 0) { + if (buffer.length !== 0) { this.socket.write(buffer); } @@ -711,7 +729,7 @@ export class OutboundPacketHandler { } public queue(packet: Packet, updateTask: boolean = false): void { - if(!this.socket || this.socket.destroyed) { + if (!this.socket || this.socket.destroyed) { return; } @@ -730,16 +748,16 @@ export class OutboundPacketHandler { } private getChunkPositionOffset(x: number, y: number, chunk: Chunk): number { - const offsetX = x - ((chunk.position.x + 6) * 8); - const offsetY = y - ((chunk.position.y + 6) * 8); - return (offsetX * 16 + offsetY); + const offsetX = x - (chunk.position.x + 6) * 8; + const offsetY = y - (chunk.position.y + 6) * 8; + return offsetX * 16 + offsetY; } - private getChunkOffset(chunk: Chunk): { offsetX: number, offsetY: number } { + private getChunkOffset(chunk: Chunk): { offsetX: number; offsetY: number } { let offsetX = (chunk.position.x + 6) * 8; let offsetY = (chunk.position.y + 6) * 8; - offsetX -= (this.player.lastMapRegionUpdatePosition.chunkX * 8); - offsetY -= (this.player.lastMapRegionUpdatePosition.chunkY * 8); + offsetX -= this.player.lastMapRegionUpdatePosition.chunkX * 8; + offsetY -= this.player.lastMapRegionUpdatePosition.chunkY * 8; return { offsetX, offsetY }; } @@ -751,7 +769,7 @@ export class OutboundPacketHandler { return Buffer.from(buffer); } - private segment(container: ItemContainer, start: number): { bitset: number, buffer: Buffer } { + private segment(container: ItemContainer, start: number): { bitset: number; buffer: Buffer } { const bound = 7 * 8; const payload = new Packet(-1, PacketType.FIXED, bound); @@ -778,5 +796,4 @@ export class OutboundPacketHandler { return { bitset, buffer: this.strip(payload) }; } - } diff --git a/src/engine/net/packet.ts b/src/engine/net/packet.ts index 5e72d5ced..095efcea2 100644 --- a/src/engine/net/packet.ts +++ b/src/engine/net/packet.ts @@ -1,5 +1,5 @@ -import type { Isaac } from './isaac'; import { ByteBuffer } from '@runejs/common'; +import type { Isaac } from './isaac'; /** * The type of packet; Fixed, Dynamic Small (sized byte), or Dynamic Large (sized short) @@ -7,14 +7,13 @@ import { ByteBuffer } from '@runejs/common'; export enum PacketType { FIXED = 'FIXED', DYNAMIC_SMALL = 'DYNAMIC_SMALL', - DYNAMIC_LARGE = 'DYNAMIC_LARGE' + DYNAMIC_LARGE = 'DYNAMIC_LARGE', } /** * A single packet to be sent to the game client. */ export class Packet extends ByteBuffer { - private readonly _packetId: number; private readonly _type: PacketType = PacketType.FIXED; @@ -28,7 +27,7 @@ export class Packet extends ByteBuffer { const packetSize = this.writerIndex; let bufferSize = packetSize + 1; // +1 for the packet id - if(this.type !== PacketType.FIXED) { + if (this.type !== PacketType.FIXED) { bufferSize += this.type === PacketType.DYNAMIC_SMALL ? 1 : 2; } @@ -37,10 +36,10 @@ export class Packet extends ByteBuffer { let copyStart = 1; - if(this.type === PacketType.DYNAMIC_SMALL) { + if (this.type === PacketType.DYNAMIC_SMALL) { buffer.put(packetSize, 'BYTE'); copyStart = 2; - } else if(this.type === PacketType.DYNAMIC_LARGE) { + } else if (this.type === PacketType.DYNAMIC_LARGE) { buffer.put(packetSize, 'SHORT'); copyStart = 3; } diff --git a/src/engine/plugins/content-plugin.ts b/src/engine/plugins/content-plugin.ts index 5f204394e..ce24df5a3 100644 --- a/src/engine/plugins/content-plugin.ts +++ b/src/engine/plugins/content-plugin.ts @@ -1,9 +1,8 @@ -import { logger } from '@runejs/common'; -import { getFiles } from '@runejs/common/fs'; import { join } from 'path'; -import type { Quest } from '@engine/world/actor/player/quest'; import type { ActionHook } from '@engine/action/hook/action-hook'; - +import type { Quest } from '@engine/world/actor/player/quest'; +import { logger } from '@runejs/common'; +import { getFiles } from '@runejs/common/fs'; /** * The definition of a single content plugin. @@ -14,7 +13,6 @@ export class ContentPlugin { public quests?: Quest[]; } - /** * Searches for and parses all plugin files within the /plugins directory. */ @@ -23,32 +21,32 @@ export async function loadPluginFiles(): Promise { const relativeDir = join('..', '..', 'plugins'); const plugins: ContentPlugin[] = []; - for await(const path of getFiles(pluginDir, { type: 'whitelist', list: ['.plugin.js', 'index.js'] })) { + for await (const path of getFiles(pluginDir, { type: 'whitelist', list: ['.plugin.js', 'index.js'] })) { const location = join(relativeDir, path.substring(pluginDir.length).replace('.js', '')); try { let pluginFile = require(location); - if(!pluginFile) { + if (!pluginFile) { continue; } - if(pluginFile.default) { + if (pluginFile.default) { pluginFile = pluginFile.default; } const plugin = pluginFile as ContentPlugin; - if(!plugin.pluginId) { + if (!plugin.pluginId) { logger.error(`Error loading plugin: Plugin ID not provided for .plugin file at ${path}`); continue; } - if(plugins.find(loadedPlugin => loadedPlugin.pluginId === plugin.pluginId)) { + if (plugins.find(loadedPlugin => loadedPlugin.pluginId === plugin.pluginId)) { logger.error(`Error loading plugin: Duplicate plugin ID ${plugin.pluginId} at ${path}`); continue; } plugins.push(plugin); - } catch(error) { + } catch (error) { logger.error(`Error loading plugin file at ${location}:`); logger.error(error); } diff --git a/src/engine/plugins/loader.ts b/src/engine/plugins/loader.ts index 8bdc05576..75c62cd5d 100644 --- a/src/engine/plugins/loader.ts +++ b/src/engine/plugins/loader.ts @@ -1,5 +1,5 @@ import type { ActionType } from '@engine/action/action-pipeline'; -import { sortActionHooks, type ActionHook } from '@engine/action/hook/action-hook'; +import { type ActionHook, sortActionHooks } from '@engine/action/hook/action-hook'; import { loadPluginFiles } from '@engine/plugins/content-plugin'; import { Quest } from '@engine/world/actor/player/quest'; import { logger } from '@runejs/common'; @@ -37,23 +37,24 @@ export async function loadPlugins(): Promise { const pluginActionHookList = plugins?.filter(plugin => !!plugin?.hooks)?.map(plugin => plugin.hooks); - if(pluginActionHookList && pluginActionHookList.length !== 0) { - pluginActionHookList.reduce( - (a, b) => (a || []).concat(b || []))?.forEach(action => { - if(!(action instanceof Quest)) { - if(!actionHookMap[action.type]) { - actionHookMap[action.type] = []; - } + if (pluginActionHookList && pluginActionHookList.length !== 0) { + pluginActionHookList + .reduce((a, b) => (a || []).concat(b || [])) + ?.forEach(action => { + if (!(action instanceof Quest)) { + if (!actionHookMap[action.type]) { + actionHookMap[action.type] = []; + } - actionHookMap[action.type]!.push(action); - } else { - if(!actionHookMap['quest']) { - actionHookMap['quest'] = []; - } + actionHookMap[action.type]!.push(action); + } else { + if (!actionHookMap['quest']) { + actionHookMap['quest'] = []; + } - actionHookMap['quest'].push(action); - } - }); + actionHookMap['quest'].push(action); + } + }); } else { logger.warn(`No action hooks detected - update plugins.`); } @@ -69,7 +70,5 @@ export async function loadPlugins(): Promise { } // @TODO implement proper sorting rules - Object.keys(actionHookMap) - .forEach(key => actionHookMap[key] = - sortActionHooks(actionHookMap[key])); + Object.keys(actionHookMap).forEach(key => (actionHookMap[key] = sortActionHooks(actionHookMap[key]))); } diff --git a/src/engine/plugins/reload-content.ts b/src/engine/plugins/reload-content.ts index 40924495b..0f6dd59ae 100644 --- a/src/engine/plugins/reload-content.ts +++ b/src/engine/plugins/reload-content.ts @@ -1,34 +1,25 @@ import { sep } from 'path'; -import { loadPlugins } from '@engine/plugins/loader'; -import { logger } from '@runejs/common'; -import type { Player } from '@engine/world/actor/player/player'; import { loadGameConfigurations } from '@engine/config/config-handler'; import { loadPackets } from '@engine/net/inbound-packet-handler'; +import { loadPlugins } from '@engine/plugins/loader'; +import type { Player } from '@engine/world/actor/player/player'; +import { logger } from '@runejs/common'; -export const reloadContentCommands = [ - 'plugins', 'reload', 'content', 'hotload', 'refresh', 'restart', 'r' -]; +export const reloadContentCommands = ['plugins', 'reload', 'content', 'hotload', 'refresh', 'restart', 'r']; export const reloadContent = async (player: Player, isConsole: boolean = false) => { player.sendLogMessage(' ', isConsole); player.sendLogMessage('Deleting content cache...', isConsole); - const includeList = [ - 'plugins' - ].map(p => sep + p + sep); + const includeList = ['plugins'].map(p => sep + p + sep); - const ignoreList = [ - 'node_modules', - 'engine', - 'server' - ].map(p => sep + p + sep); + const ignoreList = ['node_modules', 'engine', 'server'].map(p => sep + p + sep); const pluginCache: string[] = []; const cacheKeys = Object.keys(require.cache); // Delete node cache for all the old JS plugins - cacheLoop: - for (const cacheKey of cacheKeys) { + cacheLoop: for (const cacheKey of cacheKeys) { const cachedItem = require.cache[cacheKey]; if (!cachedItem) { diff --git a/src/engine/task/impl/actor-actor-interaction-task.ts b/src/engine/task/impl/actor-actor-interaction-task.ts index e14bfc6be..d64b9705e 100644 --- a/src/engine/task/impl/actor-actor-interaction-task.ts +++ b/src/engine/task/impl/actor-actor-interaction-task.ts @@ -10,7 +10,10 @@ import { ActorWalkToTask } from './actor-walk-to-task'; * * @author jameskmonger */ -export abstract class ActorActorInteractionTask extends ActorWalkToTask Position> { +export abstract class ActorActorInteractionTask extends ActorWalkToTask< + TActor, + () => Position +> { private _other: TOtherActor; /** @@ -19,18 +22,13 @@ export abstract class ActorActorInteractionTask otherActor.position, // TODO (jkm) handle other actor size 1, - walkOnStart + walkOnStart, ); if (!otherActor) { diff --git a/src/engine/task/impl/actor-landscape-object-interaction-task.ts b/src/engine/task/impl/actor-landscape-object-interaction-task.ts index 77018f813..bd2bf4ae7 100644 --- a/src/engine/task/impl/actor-landscape-object-interaction-task.ts +++ b/src/engine/task/impl/actor-landscape-object-interaction-task.ts @@ -1,8 +1,8 @@ -import type { LandscapeObject } from '@runejs/filestore'; import { activeWorld } from '@engine/world'; -import { ActorWalkToTask } from './actor-walk-to-task'; import type { Actor } from '@engine/world/actor/actor'; import { Position } from '@engine/world/position'; +import type { LandscapeObject } from '@runejs/filestore'; +import { ActorWalkToTask } from './actor-walk-to-task'; /** * A task for an actor to interact with a {@link LandscapeObject}. @@ -22,18 +22,18 @@ export abstract class ActorLandscapeObjectInteractionTask extends Task { */ constructor( protected readonly actor: TActor, - config?: TaskConfig + config?: TaskConfig, ) { super(config); diff --git a/src/engine/task/impl/actor-teleport-task.ts b/src/engine/task/impl/actor-teleport-task.ts index 3906be173..0f9a8c822 100644 --- a/src/engine/task/impl/actor-teleport-task.ts +++ b/src/engine/task/impl/actor-teleport-task.ts @@ -14,13 +14,10 @@ export class ActorTeleportTask extends ActorTask { describe('when enqueueing a task', () => { let executeMock: jest.Mock; - let task: Task + let task: Task; beforeEach(() => { ({ task, executeMock } = createMockTask()); }); @@ -59,7 +59,7 @@ describe('TaskScheduler', () => { const stackGroup = 'foo'; let firstExecuteMock: jest.Mock; - let firstTask: Task + let firstTask: Task; beforeEach(() => { ({ task: firstTask, executeMock: firstExecuteMock } = createMockTask(interval, stackType, stackGroup)); }); @@ -90,7 +90,7 @@ describe('TaskScheduler', () => { describe('when clearing the scheduler', () => { let executeMock: jest.Mock; - let task: Task + let task: Task; beforeEach(() => { ({ task, executeMock } = createMockTask()); }); diff --git a/src/engine/task/task-scheduler.ts b/src/engine/task/task-scheduler.ts index 2c481564f..936ab8f22 100644 --- a/src/engine/task/task-scheduler.ts +++ b/src/engine/task/task-scheduler.ts @@ -23,7 +23,7 @@ export class TaskScheduler { */ public tick(): void { // Add any pending tasks to the running list - while(this.pendingTasks.isNotEmpty) { + while (this.pendingTasks.isNotEmpty) { const task = this.pendingTasks.dequeue(); if (!task || !task.isActive) { @@ -34,7 +34,7 @@ export class TaskScheduler { } // Use an iterator so that we can remove tasks from the list while iterating - for(const [index, task] of this.runningTasks.entries()) { + for (const [index, task] of this.runningTasks.entries()) { if (!task) { continue; } @@ -63,7 +63,7 @@ export class TaskScheduler { // if the task can't stack with others of a similar type, we need to stop them if (task.stackType === TaskStackType.NEVER) { // Use an iterator so that we can remove tasks from the list while iterating - for(const [index, otherTask] of this.runningTasks.entries()) { + for (const [index, otherTask] of this.runningTasks.entries()) { if (!otherTask) { continue; } @@ -74,7 +74,7 @@ export class TaskScheduler { } } - for(const otherTask of this.pendingTasks.items) { + for (const otherTask of this.pendingTasks.items) { if (!otherTask) { continue; } diff --git a/src/engine/task/task.test.ts b/src/engine/task/task.test.ts index 0fbf203c0..94a37eeef 100644 --- a/src/engine/task/task.test.ts +++ b/src/engine/task/task.test.ts @@ -1,4 +1,4 @@ -import { Task } from './task' +import { Task } from './task'; import { TaskStackType } from './types'; import { createMockTask } from './utils/_testing'; @@ -15,12 +15,12 @@ describe('Task', () => { const immediate = false; let executeMock: jest.Mock; - let task: Task + let task: Task; describe('and repeat is true', () => { const repeat = false; beforeEach(() => { - ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat, )); + ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat)); }); describe('when ticked once', () => { @@ -74,7 +74,6 @@ describe('Task', () => { }); }); - describe('when interval is 2', () => { const interval = 2; @@ -82,7 +81,7 @@ describe('Task', () => { const repeat = false; let executeMock: jest.Mock; - let task: Task + let task: Task; describe('and immediate is true', () => { const immediate = true; @@ -153,7 +152,7 @@ describe('Task', () => { beforeEach(() => { onStopMock = jest.fn(); executeMock = jest.fn(); - task = new class extends Task { + task = new (class extends Task { constructor() { super(); } @@ -165,7 +164,7 @@ describe('Task', () => { public onStop(): void { onStopMock(); } - } + })(); }); describe('when the task is stopped', () => { diff --git a/src/engine/task/task.ts b/src/engine/task/task.ts index e4154180e..f8f06e91a 100644 --- a/src/engine/task/task.ts +++ b/src/engine/task/task.ts @@ -7,7 +7,7 @@ const DEFAULT_TASK_CONFIG: Required = { stackGroup: TaskStackGroup.ACTION, immediate: false, breakTypes: [], - repeat: true + repeat: true, }; function readConfigValue(key: keyof TaskConfig, config?: TaskConfig): any { diff --git a/src/engine/task/types.ts b/src/engine/task/types.ts index f7151c598..758103397 100644 --- a/src/engine/task/types.ts +++ b/src/engine/task/types.ts @@ -48,34 +48,36 @@ export enum TaskBreakType { * * @author jameskmonger */ -export type TaskConfig = Partial>; + /** + * Should the task be repeated indefinitely? + */ + repeat: boolean; + }> +>; diff --git a/src/engine/task/utils/_testing.ts b/src/engine/task/utils/_testing.ts index 2926173ec..408ae4991 100644 --- a/src/engine/task/utils/_testing.ts +++ b/src/engine/task/utils/_testing.ts @@ -8,10 +8,10 @@ export function createMockTask( stackGroup: string = TaskStackGroup.ACTION, immediate: boolean = false, breakTypes: TaskBreakType[] = [], - repeat: boolean = true -){ + repeat: boolean = true, +) { const executeMock = jest.fn(); - const task = new class extends Task { + const task = new (class extends Task { constructor() { super({ interval, @@ -19,14 +19,14 @@ export function createMockTask( stackGroup, immediate, breakTypes, - repeat + repeat, }); } public execute(): void { executeMock(); } - } + })(); - return { task, executeMock } + return { task, executeMock }; } diff --git a/src/engine/util/address.ts b/src/engine/util/address.ts index 1383cf714..bee84af68 100644 --- a/src/engine/util/address.ts +++ b/src/engine/util/address.ts @@ -1,10 +1,10 @@ export const addressToInt = (address: string): number => { - if(!address) { + if (!address) { return 0; } const parts = address.split('.'); - if(!parts || parts.length !== 4) { + if (!parts || parts.length !== 4) { return 0; } diff --git a/src/engine/util/colors.ts b/src/engine/util/colors.ts index 1fa6dd5f5..9c225ccf6 100644 --- a/src/engine/util/colors.ts +++ b/src/engine/util/colors.ts @@ -1,8 +1,8 @@ -export function hexToRgb(hex: number): { r: number, b: number, g: number } { +export function hexToRgb(hex: number): { r: number; b: number; g: number } { return { r: (hex >> 16) & 0xff, g: (hex >> 8) & 0xff, - b: hex & 0xff + b: hex & 0xff, }; } @@ -23,7 +23,7 @@ export function hexToHexString(hex: number): string { } export function rgbTo16Bit(r: number, g: number, b: number): number { - return ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f) << 0; + return ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | ((b & 0x1f) << 0); } export const colors = { @@ -32,5 +32,5 @@ export const colors = { red: 0xff0000, black: 0x000000, blue: 0x01bdfe, - lightred: 0xef101f + lightred: 0xef101f, }; diff --git a/src/engine/util/error-handling.ts b/src/engine/util/error-handling.ts index 47955c096..2dc4245e2 100644 --- a/src/engine/util/error-handling.ts +++ b/src/engine/util/error-handling.ts @@ -20,22 +20,19 @@ export class ActionsCancelledWarning extends Error { } } -const warnings = [ - WidgetsClosedWarning, - ActionsCancelledWarning -]; +const warnings = [WidgetsClosedWarning, ActionsCancelledWarning]; export function initErrorHandling(): void { process.on('unhandledRejection', (error: any, promise) => { - for(const t of warnings) { - if(error instanceof t) { + for (const t of warnings) { + if (error instanceof t) { logger.warn(`Promise cancelled with warning: ${error.name}`); return; } } logger.error(`Unhandled promise rejection from ${promise}, reason: ${error}`); - if(error && error['stack']) { + if (error && error['stack']) { logger.error((error as any).stack); } }); diff --git a/src/engine/util/files.ts b/src/engine/util/files.ts index c71471c9d..b3bad67ea 100644 --- a/src/engine/util/files.ts +++ b/src/engine/util/files.ts @@ -1,41 +1,39 @@ -import util from 'util'; import fs from 'fs'; +import util from 'util'; import { watch } from 'chokidar'; import type { Observable } from 'rxjs'; import { Subject } from 'rxjs'; - const readdir = util.promisify(fs.readdir); const stat = util.promisify(fs.stat); - export async function getFiles(directory: string, blacklist: string[]); export async function getFiles(directory: string, whitelist: string[], useWhitelist: boolean); export async function* getFiles(directory: string, list: string[] = [], useWhitelist?: boolean): AsyncGenerator { const files = await readdir(directory); - for(const file of files) { + for (const file of files) { const path = directory + '/' + file; const statistics = await stat(path); - if(statistics.isDirectory()) { + if (statistics.isDirectory()) { // (Jameskmonger) I set the default value of `true` here, not sure if it is correct. for await (const child of getFiles(path, list, useWhitelist || false)) { yield child; } } else { - if(!useWhitelist) { + if (!useWhitelist) { // blacklist const invalid = list.some(item => file === item); - if(invalid) { + if (invalid) { continue; } } else { // whitelist const invalid = !list.some(item => file.endsWith(item)); - if(invalid) { + if (invalid) { continue; } } @@ -45,7 +43,6 @@ export async function* getFiles(directory: string, list: string[] = [], useWhite } } - export function watchSource(dir: string): Observable { const subject = new Subject(); const watcher = watch(dir); @@ -58,13 +55,12 @@ export function watchSource(dir: string): Observable { return subject.asObservable(); } - export function watchForChanges(dir: string, regex: RegExp): void { const watcher = watch(dir); watcher.on('ready', () => { watcher.on('all', () => { - Object.keys(require.cache).forEach((id) => { - if(regex.test(id)) { + Object.keys(require.cache).forEach(id => { + if (regex.test(id)) { delete require.cache[id]; } }); diff --git a/src/engine/util/objects.ts b/src/engine/util/objects.ts index 6232c6665..da909ec92 100644 --- a/src/engine/util/objects.ts +++ b/src/engine/util/objects.ts @@ -5,47 +5,47 @@ * @return objectC combination of objectA and objectB */ export function deepMerge(objectA: T, objectB: T): T { - if(!objectA) { + if (!objectA) { return objectB; } - if(!objectB) { + if (!objectB) { return objectA; } - if(Array.isArray(objectA)) { - return [...new Set([...objectA as any, ...objectB as any])] as any; + if (Array.isArray(objectA)) { + return [...new Set([...(objectA as any), ...(objectB as any)])] as any; } - if(typeof objectA === 'object') { + if (typeof objectA === 'object') { const newObject: T = { ...objectA }; const keys = [...new Set([...Object.keys(objectA), ...Object.keys(objectB)])]; - keys.forEach((key) => { - if(!objectA[key]) { + keys.forEach(key => { + if (!objectA[key]) { newObject[key] = objectB[key]; return; } - if(!objectB[key]){ + if (!objectB[key]) { newObject[key] = objectA[key]; } - if(Array.isArray(objectA[key])) { - if(!Array.isArray(objectB[key])) { - newObject[key] = [...objectA[key], objectB[key]]; + if (Array.isArray(objectA[key])) { + if (!Array.isArray(objectB[key])) { + newObject[key] = [...objectA[key], objectB[key]]; return; } newObject[key] = deepMerge(objectA[key], objectB[key]); return; } - if(Array.isArray(objectB[key])) { - if(!Array.isArray(objectA[key])) { - newObject[key] = [...objectB[key], objectA[key]]; + if (Array.isArray(objectB[key])) { + if (!Array.isArray(objectA[key])) { + newObject[key] = [...objectB[key], objectA[key]]; return; } console.error('Something is wrong with deepmerger', key, objectA, objectB); } - if(typeof objectA[key] === 'object' || typeof objectB === 'object') { + if (typeof objectA[key] === 'object' || typeof objectB === 'object') { newObject[key] = deepMerge(objectA[key], objectB[key]); return; } newObject[key] = objectA[key]; - }) + }); return newObject; } return objectA; diff --git a/src/engine/util/queue.test.ts b/src/engine/util/queue.test.ts index 06b3f7b18..985956ad7 100644 --- a/src/engine/util/queue.test.ts +++ b/src/engine/util/queue.test.ts @@ -1,4 +1,4 @@ -import { Queue } from './queue' +import { Queue } from './queue'; describe('Queue', () => { let queue: Queue; @@ -104,4 +104,4 @@ describe('Queue', () => { expect(items).toEqual([1, 2, 3]); }); }); -}) +}); diff --git a/src/engine/util/strings.ts b/src/engine/util/strings.ts index ae4c4d7b1..107b68a02 100644 --- a/src/engine/util/strings.ts +++ b/src/engine/util/strings.ts @@ -7,10 +7,9 @@ export const startsWithVowel = (str: string): boolean => { const firstChar = str.charAt(0); - return (firstChar === 'a' || firstChar === 'e' || firstChar === 'i' || firstChar === 'o' || firstChar === 'u'); + return firstChar === 'a' || firstChar === 'e' || firstChar === 'i' || firstChar === 'o' || firstChar === 'u'; }; - function getFont(font?: number | string) { if (font && typeof font === 'number') { return filestore.fontStore.getFontById(font); @@ -24,7 +23,7 @@ function getFont(font?: number | string) { export enum TextDecoration { Color, - Decoration + Decoration, } function getStylingType(tag: string) { @@ -40,21 +39,15 @@ function getStylingType(tag: string) { } } - // Thank you to the Apollo team for these values. :) -const charWidths = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 7, 14, 9, 12, 12, 4, 5, - 5, 10, 8, 4, 8, 4, 7, 9, 7, 9, 8, 8, 8, 9, 7, 9, 9, 4, 5, 7, - 9, 7, 9, 14, 9, 8, 8, 8, 7, 7, 9, 8, 6, 8, 8, 7, 10, 9, 9, 8, - 9, 8, 8, 6, 9, 8, 10, 8, 8, 8, 6, 7, 6, 9, 10, 5, 8, 8, 7, 8, - 8, 7, 8, 8, 4, 7, 7, 4, 10, 8, 8, 8, 8, 6, 8, 6, 8, 8, 9, 8, - 8, 8, 6, 4, 6, 12, 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 8, 11, 8, 8, 4, 8, 7, 12, 6, 7, 9, 5, 12, 5, 6, 10, 6, 6, 6, - 8, 8, 4, 5, 5, 6, 7, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 13, 8, 8, - 8, 8, 8, 4, 4, 5, 4, 8, 9, 9, 9, 9, 9, 9, 8, 10, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 6, 8, 8, 8, 8, 4, 4, 5, 4, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]; +const charWidths = [ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 7, 14, 9, 12, 12, 4, 5, 5, 10, 8, + 4, 8, 4, 7, 9, 7, 9, 8, 8, 8, 9, 7, 9, 9, 4, 5, 7, 9, 7, 9, 14, 9, 8, 8, 8, 7, 7, 9, 8, 6, 8, 8, 7, 10, 9, 9, 8, 9, 8, 8, 6, 9, 8, 10, + 8, 8, 8, 6, 7, 6, 9, 10, 5, 8, 8, 7, 8, 8, 7, 8, 8, 4, 7, 7, 4, 10, 8, 8, 8, 8, 6, 8, 6, 8, 8, 9, 8, 8, 8, 6, 4, 6, 12, 3, 10, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 8, 11, 8, 8, 4, 8, 7, 12, 6, 7, 9, 5, 12, 5, + 6, 10, 6, 6, 6, 8, 8, 4, 5, 5, 6, 7, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 13, 8, 8, 8, 8, 8, 4, 4, 5, 4, 8, 9, 9, 9, 9, 9, 9, 8, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 6, 8, 8, 8, 8, 4, 4, 5, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +]; // TODO refactor a bit export function wrapText(text: string, maxWidth: number, font?: number | string): string[] { @@ -141,36 +134,99 @@ export function wrapText(text: string, maxWidth: number, font?: number | string) remainder = currentLine.substring(lastSpace); } - decorationQueue.slice(0).reverse().map(tag => lineToPush += ``); - colorQueue.slice(0).reverse().map(tag => lineToPush += ``); + decorationQueue + .slice(0) + .reverse() + .map(tag => (lineToPush += ``)); + colorQueue + .slice(0) + .reverse() + .map(tag => (lineToPush += ``)); lines.push(lineToPush.trim()); currentLine = ''; - decorationQueue.slice(0).map(tag => currentLine += `<${tag}>`); - colorQueue.slice(0).map(tag => currentLine += `<${tag}>`); - remainingText.push(...remainder.split('').reverse()) + decorationQueue.slice(0).map(tag => (currentLine += `<${tag}>`)); + colorQueue.slice(0).map(tag => (currentLine += `<${tag}>`)); + remainingText.push(...remainder.split('').reverse()); currentWidth = 0; } - } - if(currentLine !== '\n') { + if (currentLine !== '\n') { lines.push(currentLine); - } // logger.info('split lines: ' + lines) return lines; } -const VALID_CHARS = ['_', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '!', '@', '#', '$', '%', '^', '&', - '*', '(', ')', '-', '+', '=', ':', ';', '.', '>', '<', ',', '"', - '[', ']', '|', '?', '/', '`']; +const VALID_CHARS = [ + '_', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '!', + '@', + '#', + '$', + '%', + '^', + '&', + '*', + '(', + ')', + '-', + '+', + '=', + ':', + ';', + '.', + '>', + '<', + ',', + '"', + '[', + ']', + '|', + '?', + '/', + '`', +]; export function longToString(nameLong: bigint): string { let ac: string = ''; - while(nameLong !== BigInt(0)) { + while (nameLong !== BigInt(0)) { const l1 = nameLong; nameLong = BigInt(nameLong) / BigInt(37); ac += VALID_CHARS[parseInt(l1.toString()) - parseInt(nameLong.toString()) * 37]; @@ -186,9 +242,9 @@ export function stringToLong(s: string): bigint { const c = s.charAt(i); const cc = s.charCodeAt(i); l *= BigInt(37); - if (c >= 'A' && c <= 'Z') l += BigInt((1 + cc) - 65); - else if (c >= 'a' && c <= 'z') l += BigInt((1 + cc) - 97); - else if (c >= '0' && c <= '9') l += BigInt((27 + cc) - 48); + if (c >= 'A' && c <= 'Z') l += BigInt(1 + cc - 65); + else if (c >= 'a' && c <= 'z') l += BigInt(1 + cc - 97); + else if (c >= '0' && c <= '9') l += BigInt(27 + cc - 48); } while (l % BigInt(37) == BigInt(0) && l != BigInt(0)) l /= BigInt(37); return l; diff --git a/src/engine/util/time.ts b/src/engine/util/time.ts index af71167bb..9eeb1aa50 100644 --- a/src/engine/util/time.ts +++ b/src/engine/util/time.ts @@ -4,7 +4,7 @@ export const rsTime = (date: Date): number => { }; export const daysSinceLastLogin = (lastLogin: Date): number => { - if(!lastLogin) { + if (!lastLogin) { return -1; } diff --git a/src/engine/util/varbits.ts b/src/engine/util/varbits.ts index 3f8b616df..0367c147c 100644 --- a/src/engine/util/varbits.ts +++ b/src/engine/util/varbits.ts @@ -9,7 +9,7 @@ const varbitMasks: number[] = []; * @return index to morph into */ export function getVarbitMorphIndex(varbitId, playerConfig) { - if(varbitMasks.length === 0) { + if (varbitMasks.length === 0) { let i = 2; for (let i_7_ = 0; i_7_ < 32; i_7_++) { varbitMasks[i_7_] = -1 + i; @@ -18,7 +18,7 @@ export function getVarbitMorphIndex(varbitId, playerConfig) { } const varbitDefinition = filestore.configStore.varbitStore.getVarbit(varbitId); - if(!varbitDefinition) { + if (!varbitDefinition) { throw new Error(`Could not find varbit definition for id ${varbitId}`); } @@ -28,5 +28,5 @@ export function getVarbitMorphIndex(varbitId, playerConfig) { // TODO: Unknown const i_8_ = varbitMasks[mostSignificantBit - leastSignificantBit]; const configValue = playerConfig && playerConfig[configId] ? playerConfig[configId] : 0; - return ((configValue) >> leastSignificantBit & i_8_); + return (configValue >> leastSignificantBit) & i_8_; } diff --git a/src/engine/world/actor/actor.ts b/src/engine/world/actor/actor.ts index 6901a4f2a..34140ebc8 100644 --- a/src/engine/world/actor/actor.ts +++ b/src/engine/world/actor/actor.ts @@ -1,17 +1,7 @@ -import { Subject } from 'rxjs'; -import { filter, take } from 'rxjs/operators'; -import { WalkingQueue } from './walking-queue'; -import type { Animation, Graphic } from './update-flags'; -import { UpdateFlags } from './update-flags'; -import { Skills } from './skills'; -import { Pathfinding } from './pathfinding'; -import type { ActorMetadata } from './metadata'; -import { logger } from '@runejs/common'; -import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; -import { isNpc } from './util'; import type { ActionCancelType } from '@engine/action/action-pipeline'; import { ActionPipeline } from '@engine/action/action-pipeline'; -import type { OffensiveBonuses, DefensiveBonuses, SkillBonuses } from '@engine/config/item-config'; +import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; +import type { DefensiveBonuses, OffensiveBonuses, SkillBonuses } from '@engine/config/item-config'; import type { Task } from '@engine/task/task'; import { TaskScheduler } from '@engine/task/task-scheduler'; import { activeWorld } from '@engine/world'; @@ -20,16 +10,23 @@ import type { WorldInstance } from '@engine/world/instances'; import type { Item } from '@engine/world/items/item'; import { ItemContainer } from '@engine/world/items/item-container'; import { Position } from '@engine/world/position'; - +import { logger } from '@runejs/common'; +import { Subject } from 'rxjs'; +import { filter, take } from 'rxjs/operators'; +import type { ActorMetadata } from './metadata'; +import { Pathfinding } from './pathfinding'; +import { Skills } from './skills'; +import type { Animation, Graphic } from './update-flags'; +import { UpdateFlags } from './update-flags'; +import { isNpc } from './util'; +import { WalkingQueue } from './walking-queue'; export type ActorType = 'player' | 'npc'; - /** * Handles an entity within the game world. */ export abstract class Actor { - public readonly type: ActorType; public readonly updateFlags: UpdateFlags = new UpdateFlags(); public readonly skills: Skills = new Skills(this); @@ -76,7 +73,7 @@ export abstract class Actor { private _walkDirection: number; private _runDirection: number; private _faceDirection: number; - private _bonuses: { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses }; + private _bonuses: { offensive: OffensiveBonuses; defensive: DefensiveBonuses; skill: SkillBonuses }; private readonly scheduler = new TaskScheduler(); @@ -99,12 +96,21 @@ export abstract class Actor { * If the task has a stack type of `NEVER`, other tasks in the same {@link TaskStackGroup} will be cancelled. */ public enqueueTask(taskClass: new (actor: Actor) => Task, ...args: never[]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Task, args: [ T1, T2, T3, T4, T5, T6 ]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Task, args: [ T1, T2, T3, T4, T5 ]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Task, args: [ T1, T2, T3, T4 ]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3) => Task, args: [ T1, T2, T3 ]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2) => Task, args: [ T1, T2 ]): void; - public enqueueTask(taskClass: new (actor: Actor, arg1: T1) => Task, args: [ T1 ]): void; + public enqueueTask( + taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Task, + args: [T1, T2, T3, T4, T5, T6], + ): void; + public enqueueTask( + taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Task, + args: [T1, T2, T3, T4, T5], + ): void; + public enqueueTask( + taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Task, + args: [T1, T2, T3, T4], + ): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3) => Task, args: [T1, T2, T3]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2) => Task, args: [T1, T2]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1) => Task, args: [T1]): void; public enqueueTask(taskClass: new (actor: Actor, ...args: T[]) => Task, args: T[]): void { if (!this.active) { logger.warn(`Attempted to instantiate task for inactive actor`); @@ -112,13 +118,9 @@ export abstract class Actor { } if (args) { - this.enqueueBaseTask( - new taskClass(this, ...args) - ); + this.enqueueBaseTask(new taskClass(this, ...args)); } else { - this.enqueueBaseTask( - new taskClass(this) - ); + this.enqueueBaseTask(new taskClass(this)); } } @@ -152,57 +154,67 @@ export abstract class Actor { public clearBonuses(): void { this._bonuses = { offensive: { - speed: 0, stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 + speed: 0, + stab: 0, + slash: 0, + crush: 0, + magic: 0, + ranged: 0, }, defensive: { - stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 + stab: 0, + slash: 0, + crush: 0, + magic: 0, + ranged: 0, }, skill: { - strength: 0, prayer: 0 - } + strength: 0, + prayer: 0, + }, }; } public moveBehind(target: Actor): boolean { - if(this.position.level !== target.position.level) { + if (this.position.level !== target.position.level) { return false; } const distance = Math.floor(this.position.distanceBetween(target.position)); - if(distance > 16) { + if (distance > 16) { this.clearFaceActor(); return false; } let ignoreDestination = true; let desiredPosition = target.position; - if(target.lastMovementPosition) { + if (target.lastMovementPosition) { desiredPosition = target.lastMovementPosition; ignoreDestination = false; } this.pathfinding.walkTo(desiredPosition, { pathingSearchRadius: distance + 2, - ignoreDestination + ignoreDestination, }); return true; } public moveTo(target: Actor): boolean { - if(this.position.level !== target.position.level) { + if (this.position.level !== target.position.level) { return false; } const distance = Math.floor(this.position.distanceBetween(target.position)); - if(distance > 16) { + if (distance > 16) { this.clearFaceActor(); return false; } this.pathfinding.walkTo(target.position, { pathingSearchRadius: distance + 2, - ignoreDestination: true + ignoreDestination: true, }); return true; @@ -214,20 +226,22 @@ export abstract class Actor { this.moveBehind(target); const subscription = target.walkingQueue.movementEvent.subscribe(() => { - if(!this.moveBehind(target)) { + if (!this.moveBehind(target)) { // (Jameskmonger) actionsCancelled is deprecated, casting this to satisfy the typecheck for now this.actionsCancelled.next(null as unknown as ActionCancelType); } }); - this.actionsCancelled.pipe( - filter(type => type !== 'pathing-movement'), - take(1) - ).subscribe(() => { - subscription.unsubscribe(); - this.face(null); - delete this.metadata.following; - }); + this.actionsCancelled + .pipe( + filter(type => type !== 'pathing-movement'), + take(1), + ) + .subscribe(() => { + subscription.unsubscribe(); + this.face(null); + delete this.metadata.following; + }); } public walkTo(target: Actor): boolean; @@ -237,11 +251,11 @@ export abstract class Actor { const distance = Math.floor(this.position.distanceBetween(desiredPosition)); - if(distance <= 1) { + if (distance <= 1) { return false; } - if(distance > 16) { + if (distance > 16) { this.clearFaceActor(); this.metadata.faceActorClearedByWalking = true; return false; @@ -249,34 +263,39 @@ export abstract class Actor { this.pathfinding.walkTo(desiredPosition, { pathingSearchRadius: distance + 2, - ignoreDestination: true + ignoreDestination: true, }); return true; } - public face(face: Position | Actor | null, clearWalkingQueue: boolean = true, autoClear: boolean = true, clearedByWalking: boolean = true): void { - if(face === null) { + public face( + face: Position | Actor | null, + clearWalkingQueue: boolean = true, + autoClear: boolean = true, + clearedByWalking: boolean = true, + ): void { + if (face === null) { this.clearFaceActor(); this.updateFlags.facePosition = null; return; } - if(face instanceof Position) { + if (face instanceof Position) { this.updateFlags.facePosition = face; - } else if(face instanceof Actor) { + } else if (face instanceof Actor) { this.updateFlags.faceActor = face; this.metadata.faceActor = face; this.metadata.faceActorClearedByWalking = clearedByWalking; - if(autoClear) { + if (autoClear) { setTimeout(() => { this.clearFaceActor(); }, 20000); } } - if(clearWalkingQueue) { + if (clearWalkingQueue) { this.walkingQueue.clear(); this.walkingQueue.valid = false; } @@ -290,7 +309,7 @@ export abstract class Actor { } public playAnimation(animation: number | Animation | null): void { - if(typeof animation === 'number') { + if (typeof animation === 'number') { animation = { id: animation, delay: 0 }; } @@ -302,7 +321,7 @@ export abstract class Actor { } public playGraphics(graphics: number | Graphic): void { - if(typeof graphics === 'number') { + if (typeof graphics === 'number') { graphics = { id: graphics, delay: 0, height: 120 }; } @@ -346,23 +365,31 @@ export abstract class Actor { } public initiateRandomMovement(): void { - this.enqueueBaseTask(new QueueableTask([], this, () => { - this.moveSomewhere(); - return { - callbackResult: true, - shouldContinueLooping: true, - }; - }, null, null)) + this.enqueueBaseTask( + new QueueableTask( + [], + this, + () => { + this.moveSomewhere(); + return { + callbackResult: true, + shouldContinueLooping: true, + }; + }, + null, + null, + ), + ); } public moveSomewhere(): void { - if(!this.canMove()) { + if (!this.canMove()) { return; } - if(isNpc(this)) { + if (isNpc(this)) { const nearbyPlayers = activeWorld.findNearbyPlayers(this.position, 24, this.instance.instanceId); - if(nearbyPlayers.length === 0) { + if (nearbyPlayers.length === 0) { // No need for this actor to move if there are no players nearby to witness it, save some memory. :) return; } @@ -370,7 +397,7 @@ export abstract class Actor { const movementChance = Math.floor(Math.random() * 10); - if(movementChance < 7) { + if (movementChance < 7) { return; } @@ -378,17 +405,17 @@ export abstract class Actor { let py = this.position.y; let movementAllowed = false; - while(!movementAllowed) { + while (!movementAllowed) { px = this.position.x; py = this.position.y; const moveXChance = Math.floor(Math.random() * 10); - if(moveXChance > 6) { + if (moveXChance > 6) { const moveXAmount = Math.floor(Math.random() * 5); const moveXMod = Math.floor(Math.random() * 2); - if(moveXMod === 0) { + if (moveXMod === 0) { px -= moveXAmount; } else { px += moveXAmount; @@ -397,11 +424,11 @@ export abstract class Actor { const moveYChance = Math.floor(Math.random() * 10); - if(moveYChance > 6) { + if (moveYChance > 6) { const moveYAmount = Math.floor(Math.random() * 5); const moveYMod = Math.floor(Math.random() * 2); - if(moveYMod === 0) { + if (moveYMod === 0) { py -= moveYAmount; } else { py += moveYAmount; @@ -410,14 +437,14 @@ export abstract class Actor { let valid = true; - if(!this.withinBounds(px, py)) { + if (!this.withinBounds(px, py)) { valid = false; } movementAllowed = valid; } - if(px !== this.position.x || py !== this.position.y) { + if (px !== this.position.x || py !== this.position.y) { this.walkingQueue.clear(); this.walkingQueue.valid = true; this.walkingQueue.add(px, py); @@ -425,7 +452,7 @@ export abstract class Actor { } public forceMovement(direction: number, steps: number): void { - if(!this.canMove()) { + if (!this.canMove()) { return; } @@ -433,29 +460,28 @@ export abstract class Actor { let py = this.position.y; let movementAllowed = false; - while(!movementAllowed) { + while (!movementAllowed) { px = this.position.x; py = this.position.y; const movementDirection = directionFromIndex(direction); - if(!movementDirection) { + if (!movementDirection) { return; } let valid = true; - for(let step = 0; step < steps; step++) { + for (let step = 0; step < steps; step++) { px += movementDirection.deltaX; py += movementDirection.deltaY; - if(!this.withinBounds(px, py)) { + if (!this.withinBounds(px, py)) { valid = false; } - } movementAllowed = valid; } - if(px !== this.position.x || py !== this.position.y) { + if (px !== this.position.x || py !== this.position.y) { this.walkingQueue.clear(); this.walkingQueue.valid = true; this.walkingQueue.add(px, py); @@ -493,7 +519,7 @@ export abstract class Actor { } public set position(value: Position) { - if(!this._position) { + if (!this._position) { this._lastMapRegionUpdatePosition = value; } @@ -556,7 +582,7 @@ export abstract class Actor { this._instance = value; } - public get bonuses(): { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses } { + public get bonuses(): { offensive: OffensiveBonuses; defensive: DefensiveBonuses; skill: SkillBonuses } { return this._bonuses; } } diff --git a/src/engine/world/actor/combat.ts b/src/engine/world/actor/combat.ts index 262669af3..d7f908ed3 100644 --- a/src/engine/world/actor/combat.ts +++ b/src/engine/world/actor/combat.ts @@ -1,5 +1,5 @@ -import * as combatStylesImport from '../../../../data/config/combat-styles.json'; import type { SkillName } from '@engine/world/actor/skills'; +import * as combatStylesImport from '../../../../data/config/combat-styles.json'; export interface CombatStyles { [key: string]: CombatStyle[]; diff --git a/src/engine/world/actor/dialogue.ts b/src/engine/world/actor/dialogue.ts index fcb1787df..321fda522 100644 --- a/src/engine/world/actor/dialogue.ts +++ b/src/engine/world/actor/dialogue.ts @@ -1,12 +1,11 @@ +import { findNpc } from '@engine/config/config-handler'; +import { wrapText } from '@engine/util/strings'; import type { Npc } from '@engine/world/actor/npc'; import { Player } from '@engine/world/actor/player/player'; -import { filestore } from '@server/game/game-server'; import { logger } from '@runejs/common'; -import _ from 'lodash'; -import { wrapText } from '@engine/util/strings'; -import { findNpc } from '@engine/config/config-handler'; import type { ParentWidget, TextWidget } from '@runejs/filestore'; - +import { filestore } from '@server/game/game-server'; +import _ from 'lodash'; export enum Emote { POMPOUS = 'POMPOUS', @@ -29,7 +28,7 @@ export enum Emote { BLANK_STARE = 'BLANK_STARE', SINGLE_WORD = 'SINGLE_WORD', EVIL_STARE = 'EVIL_STARE', - LAUGH_EVIL = 'LAUGH_EVIL' + LAUGH_EVIL = 'LAUGH_EVIL', } // A big thanks to Dust R I P for all these emotes! @@ -104,12 +103,12 @@ enum EmoteAnimation { EASTER_BUNNY_4LINE = 1827, } -const nonLineEmotes = [ Emote.BLANK_STARE, Emote.SINGLE_WORD, Emote.EVIL_STARE, Emote.LAUGH_EVIL ]; -const playerWidgetIds = [ 64, 65, 66, 67 ]; -const npcWidgetIds = [ 241, 242, 243, 244 ]; -const optionWidgetIds = [ 228, 230, 232, 234, 235 ]; -const continuableTextWidgetIds = [ 210, 211, 212, 213, 214 ]; -const textWidgetIds = [ 215, 216, 217, 218, 219 ]; +const nonLineEmotes = [Emote.BLANK_STARE, Emote.SINGLE_WORD, Emote.EVIL_STARE, Emote.LAUGH_EVIL]; +const playerWidgetIds = [64, 65, 66, 67]; +const npcWidgetIds = [241, 242, 243, 244]; +const optionWidgetIds = [228, 230, 232, 234, 235]; +const continuableTextWidgetIds = [210, 211, 212, 213, 214]; +const textWidgetIds = [215, 216, 217, 218, 219]; const titledTextWidgetId = 372; /** @@ -131,7 +130,7 @@ function wrapDialogueText(text: string, type: 'ACTOR' | 'TEXT'): string[] { width = widget.width; break; default: - throw new Error(`Unhandled widget type: ${ type }`); + throw new Error(`Unhandled widget type: ${type}`); } return wrapText(text, width, widget.fontId); @@ -150,7 +149,10 @@ function parseDialogueFunctionArgs(func: Function): string[] | null { return null; } - const arg = str.substring(0, argEndIndex).replace(/[\\(\\) ]/g, '').trim(); + const arg = str + .substring(0, argEndIndex) + .replace(/[\\(\\) ]/g, '') + .trim(); if (!arg || arg.length === 0) { return null; } @@ -172,8 +174,10 @@ interface NpcParticipant { } class DialogueFunction { - constructor(public type: string, public execute: Function) { - } + constructor( + public type: string, + public execute: Function, + ) {} } export const execute = (execute: Function): DialogueFunction => new DialogueFunction('execute', execute); @@ -190,8 +194,7 @@ class GoToAction implements DialogueAction { public tag: string; public type = 'GOTO'; - constructor(public to: string | Function) { - } + constructor(public to: string | Function) {} } interface ActorDialogueAction extends DialogueAction { @@ -246,7 +249,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di let args = parseDialogueFunctionArgs(dialogueAction); if (args === null) { - args = [ '()' ]; + args = ['()']; } const dialogueType = args[0]; @@ -299,7 +302,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di const optionsDialogueAction: OptionsDialogueAction = { options: {}, tag: tag || '', - type: 'OPTIONS' + type: 'OPTIONS', }; if (!tag) { @@ -329,7 +332,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } else if (dialogueType === 'titled') { // Text-only dialogue (no option to continue). - const [ title, text ] = dialogueAction(); + const [title, text] = dialogueAction(); const lines = wrapDialogueText(text, 'TEXT'); while (lines.length < 4) { @@ -345,7 +348,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } else { // Player or Npc dialogue. - let dialogueDetails: [ Emote, string ]; + let dialogueDetails: [Emote, string]; let npc: Npc | number | string = -1; if (dialogueType !== 'player') { @@ -374,13 +377,13 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } const emote = dialogueDetails[0] as Emote; - const text = carryoverDialogue.join(' ') + dialogueDetails[1] as string; + const text = (carryoverDialogue.join(' ') + dialogueDetails[1]) as string; carryoverDialogue = []; let lines = wrapDialogueText(text, 'ACTOR'); // logger.info('length = ' + lines.length + ' - lines equals this: ' + lines); - const animation = nonLineEmotes.indexOf(emote) !== -1 ? EmoteAnimation[emote] : EmoteAnimation[`${ emote }_${ lines.length }LINE`]; + const animation = nonLineEmotes.indexOf(emote) !== -1 ? EmoteAnimation[emote] : EmoteAnimation[`${emote}_${lines.length}LINE`]; if (!tag) { logger.warn('No tag provided for npc dialogue.'); @@ -397,7 +400,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di animation, lines, tag: tag || '', - type: 'NPC' + type: 'NPC', }; parsedDialogueTree.push(npcDialogueAction); @@ -412,7 +415,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di animation, lines, tag: tag || '', - type: 'NPC' + type: 'NPC', }; parsedDialogueTree.push(npcDialogueAction); @@ -424,7 +427,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di animation, lines, tag: tag || '', - type: 'NPC' + type: 'NPC', }; parsedDialogueTree.push(npcDialogueAction); @@ -435,7 +438,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di animation, lines, tag: tag || '', - type: 'PLAYER' + type: 'PLAYER', }; parsedDialogueTree.push(playerDialogueAction); @@ -446,8 +449,12 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di return parsedDialogueTree; } -async function runDialogueAction(player: Player, dialogueAction: string | DialogueFunction | DialogueAction, - tag?: string | undefined | false, additionalOptions?: AdditionalOptions): Promise { +async function runDialogueAction( + player: Player, + dialogueAction: string | DialogueFunction | DialogueAction, + tag?: string | undefined | false, + additionalOptions?: AdditionalOptions, +): Promise { if (dialogueAction instanceof DialogueFunction && !tag) { // Code execution dialogue. dialogueAction.execute(); @@ -458,7 +465,7 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog if (dialogueAction.type === 'GOTO' && !tag) { // Goto dialogue. - const goToAction = (dialogueAction as GoToAction); + const goToAction = dialogueAction as GoToAction; if (typeof goToAction.to === 'function') { const goto: string = goToAction.to(); await runParsedDialogue(player, player.metadata.dialogueTree, goto, additionalOptions); @@ -504,8 +511,10 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog const lines = textDialogueAction.lines; if (lines.length > 5) { - throw new Error(`Too many lines for text dialogue! Dialogue has ${ lines.length } lines but ` + - `the maximum is 5: ${ JSON.stringify(lines) }`); + throw new Error( + `Too many lines for text dialogue! Dialogue has ${lines.length} lines but ` + + `the maximum is 5: ${JSON.stringify(lines)}`, + ); } widgetId = (textDialogueAction.canContinue ? continuableTextWidgetIds : textWidgetIds)[lines.length - 1]; @@ -524,8 +533,10 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog const { title, lines } = titledDialogueAction; if (lines.length > 4) { - throw new Error(`Too many lines for titled dialogue! Dialogue has ${ lines.length } lines but ` + - `the maximum is 4: ${ JSON.stringify(lines) }`); + throw new Error( + `Too many lines for titled dialogue! Dialogue has ${lines.length} lines but ` + + `the maximum is 4: ${JSON.stringify(lines)}`, + ); } widgetId = titledTextWidgetId; @@ -538,7 +549,7 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } } else if (dialogueAction.type === 'SUBTREE') { // Dialogue sub-tree. - const action = (dialogueAction as SubDialogueTreeAction); + const action = dialogueAction as SubDialogueTreeAction; if (!action.npcParticipants) { // (Jameskmonger) I added this log because the TypeScript types allow for this to be undefined, but @@ -591,8 +602,10 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog const lines = actorDialogueAction.lines; if (lines.length > 4) { - throw new Error(`Too many lines for actor dialogue! Dialogue has ${ lines.length } lines but ` + - `the maximum is 4: ${ JSON.stringify(lines) }`); + throw new Error( + `Too many lines for actor dialogue! Dialogue has ${lines.length} lines but ` + + `the maximum is 4: ${JSON.stringify(lines)}`, + ); } const animation = actorDialogueAction.animation; @@ -616,11 +629,9 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog for (let i = 0; i < lines.length; i++) { player.outgoingPackets.updateWidgetString(widgetId, 2 + i, lines[i]); } - } } - if (tag === undefined && widgetId !== -1) { const permanent = additionalOptions?.permanent || false; @@ -629,10 +640,9 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } else { player.interfaceState.openWidget(widgetId, { slot: 'chatbox', - multi: false + multi: false, }); - const widgetClosedEvent = await player.interfaceState.widgetClosed('chatbox'); if (widgetClosedEvent.data !== undefined) { if (isOptions && typeof widgetClosedEvent.data === 'number') { @@ -652,8 +662,12 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog return tag; } -async function runParsedDialogue(player: Player, dialogueTree: ParsedDialogueTree, tag?: string | undefined | false, - additionalOptions?: AdditionalOptions): Promise { +async function runParsedDialogue( + player: Player, + dialogueTree: ParsedDialogueTree, + tag?: string | undefined | false, + additionalOptions?: AdditionalOptions, +): Promise { for (let i = 0; i < dialogueTree.length; i++) { tag = await runDialogueAction(player, dialogueTree[i], tag, additionalOptions); if (tag === false) { @@ -664,8 +678,11 @@ async function runParsedDialogue(player: Player, dialogueTree: ParsedDialogueTre return tag === undefined; } -export async function dialogue(participants: (Player | NpcParticipant)[], dialogueTree: DialogueTree, - additionalOptions?: AdditionalOptions): Promise { +export async function dialogue( + participants: (Player | NpcParticipant)[], + dialogueTree: DialogueTree, + additionalOptions?: AdditionalOptions, +): Promise { const player: Player | undefined = participants.find(p => p instanceof Player); if (!player) { @@ -692,41 +709,59 @@ export async function dialogue(participants: (Player | NpcParticipant)[], dialog } } -const itemSelectionDialogueAmounts = [ - 1, 5, 'X', 'All' -]; +const itemSelectionDialogueAmounts = [1, 5, 'X', 'All']; const itemSelectionDialogues = { // 303-306 - what would you like to make? 303: { - items: [ 2, 3 ], - text: [ 7, 11 ], - options: [ [ 7, 6, 5, 4 ], [ 11, 10, 9, 8 ] ] + items: [2, 3], + text: [7, 11], + options: [ + [7, 6, 5, 4], + [11, 10, 9, 8], + ], }, 304: { - items: [ 2, 3, 4 ], - text: [ 8, 12, 16 ], - options: [ [ 8, 7, 6, 5 ], [ 12, 11, 10, 9 ], [ 16, 15, 14, 13 ] ] + items: [2, 3, 4], + text: [8, 12, 16], + options: [ + [8, 7, 6, 5], + [12, 11, 10, 9], + [16, 15, 14, 13], + ], }, 305: { - items: [ 2, 3, 4, 5 ], - text: [ 9, 13, 17, 21 ], - options: [ [ 9, 8, 7, 6 ], [ 13, 12, 11, 10 ], [ 17, 16, 15, 14 ], [ 21, 20, 19, 18 ] ] + items: [2, 3, 4, 5], + text: [9, 13, 17, 21], + options: [ + [9, 8, 7, 6], + [13, 12, 11, 10], + [17, 16, 15, 14], + [21, 20, 19, 18], + ], }, 306: { - items: [ 2, 3, 4, 5, 6 ], - text: [ 10, 14, 18, 22, 26 ], - options: [ [ 10, 9, 8, 7 ], [ 14, 13, 12, 11 ], [ 18, 17, 16, 15 ], [ 22, 21, 20, 19 ], [ 26, 25, 24, 23 ] ] + items: [2, 3, 4, 5, 6], + text: [10, 14, 18, 22, 26], + options: [ + [10, 9, 8, 7], + [14, 13, 12, 11], + [18, 17, 16, 15], + [22, 21, 20, 19], + [26, 25, 24, 23], + ], }, - 307: { // 307 - how many would you like to cook? - items: [ 2 ], - text: [ 6 ], - options: [ [ 6, 5, 4, 3 ] ] + 307: { + // 307 - how many would you like to cook? + items: [2], + text: [6], + options: [[6, 5, 4, 3]], + }, + 309: { + // 309 - how many would you like to make? + items: [2], + text: [6], + options: [[6, 5, 4, 3]], }, - 309: { // 309 - how many would you like to make? - items: [ 2 ], - text: [ 6 ], - options: [ [ 6, 5, 4, 3 ] ] - } }; export interface SelectableItem { @@ -752,7 +787,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M throw new Error(`Too many items provided to the item selection action!`); } - widgetId = (301 + items.length); + widgetId = 301 + items.length; } } @@ -770,13 +805,17 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M player.outgoingPackets.setItemOnWidget(widgetId, childId, itemInfo.itemId, itemInfo.zoom); player.outgoingPackets.moveWidgetChild(widgetId, childId, 0, itemInfo.offset); - player.outgoingPackets.updateWidgetString(widgetId, itemSelectionDialogues[widgetId].text[index], '\\n\\n\\n\\n' + itemInfo.itemName); + player.outgoingPackets.updateWidgetString( + widgetId, + itemSelectionDialogues[widgetId].text[index], + '\\n\\n\\n\\n' + itemInfo.itemName, + ); }); return new Promise((resolve, reject) => { player.interfaceState.openWidget(widgetId, { slot: 'chatbox', - multi: true + multi: true, }); let actionsSub = player.actionsCancelled.subscribe(() => { diff --git a/src/engine/world/actor/magic.ts b/src/engine/world/actor/magic.ts index c259cf41c..ec6500b4b 100644 --- a/src/engine/world/actor/magic.ts +++ b/src/engine/world/actor/magic.ts @@ -5,10 +5,5 @@ export interface Magic { BaseDamage: number; EffectID: number; DamageCalculation(): number; - - -} -export abstract class Magic { - - } +export abstract class Magic {} diff --git a/src/engine/world/actor/npc.ts b/src/engine/world/actor/npc.ts index 17bb96b98..92b89e137 100644 --- a/src/engine/world/actor/npc.ts +++ b/src/engine/world/actor/npc.ts @@ -1,27 +1,26 @@ -import { v4 } from 'uuid'; import EventEmitter from 'events'; -import { filestore } from '@server/game/game-server'; -import { activeWorld } from '@engine/world'; -import { Actor } from './actor'; -import type { SkillName } from './skills'; -import { logger } from '@runejs/common'; -import { isPlayer } from '@engine/world/actor/util'; -import { findNpc, findItem } from '@engine/config/config-handler'; +import { findItem, findNpc } from '@engine/config/config-handler'; import type { NpcCombatAnimations, NpcDetails } from '@engine/config/npc-config'; import type { NpcSpawn } from '@engine/config/npc-spawn-config'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; +import { isPlayer } from '@engine/world/actor/util'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { directionData } from '@engine/world/direction'; import type { WorldInstance } from '@engine/world/instances'; import type { Position } from '@engine/world/position'; import type { QuadtreeKey } from '@engine/world/world'; +import { logger } from '@runejs/common'; +import { filestore } from '@server/game/game-server'; +import { v4 } from 'uuid'; +import { Actor } from './actor'; +import type { SkillName } from './skills'; /** * Represents a non-player character within the game world. */ export class Npc extends Actor { - public readonly uuid: string; public readonly options: string[]; public readonly initialPosition: Position; @@ -59,19 +58,19 @@ export class Npc extends Actor { this.initialPosition = this.position.clone(); this.npcSpawn = npcSpawn; - if(instance) { + if (instance) { this.instance = instance; } - if(npcSpawn.movementRadius) { + if (npcSpawn.movementRadius) { this._movementRadius = npcSpawn.movementRadius; } - if(npcSpawn.faceDirection) { + if (npcSpawn.faceDirection) { this.faceDirection = directionData[npcSpawn.faceDirection].index; } - if(typeof npcDetails === 'number') { + if (typeof npcDetails === 'number') { this.id = npcDetails; } else { this.id = npcDetails.gameId; @@ -79,14 +78,14 @@ export class Npc extends Actor { this.animations = npcDetails.combatAnimations || {}; this.options = npcDetails.options || []; - if(npcDetails.skills) { + if (npcDetails.skills) { const skillNames = Object.keys(npcDetails.skills); - skillNames.forEach((skillName) => this.skills.setLevel(skillName as SkillName, npcDetails.skills?.[skillName] ?? 1)); + skillNames.forEach(skillName => this.skills.setLevel(skillName as SkillName, npcDetails.skills?.[skillName] ?? 1)); } } const cacheDetails = filestore.configStore.npcStore.getNpc(this.id); - if(cacheDetails) { + if (cacheDetails) { // NPC not registered on the server, but exists in the game cache - use that for our info and assume it's // Not a combatant NPC since we have no useful combat information for it. @@ -101,7 +100,7 @@ export class Npc extends Actor { turnAround: cacheDetails.animations?.turnAround || undefined, turnLeft: cacheDetails.animations?.turnLeft || undefined, turnRight: cacheDetails.animations?.turnRight || undefined, - stand: cacheDetails.animations?.stand || undefined + stand: cacheDetails.animations?.stand || undefined, }; } else { this._name = 'Unknown'; @@ -115,7 +114,7 @@ export class Npc extends Actor { activeWorld.chunkManager.getChunkForWorldPosition(this.position).addNpc(this); - if(this.movementRadius > 0) { + if (this.movementRadius > 0) { this.initiateRandomMovement(); } @@ -125,23 +124,22 @@ export class Npc extends Actor { } //This is useful so that we can tie into things like "spell casts" or events, or traps, etc to finish quests or whatever - public async processDeath(assailant: Actor, defender:Actor): Promise { - + public async processDeath(assailant: Actor, defender: Actor): Promise { return new Promise(resolve => { const deathPosition = defender.position; let deathAnim: number = animationIds.death; - deathAnim = findNpc((defender as Npc).id).combatAnimations?.death || animationIds.death + deathAnim = findNpc((defender as Npc).id).combatAnimations?.death || animationIds.death; defender.playAnimation(deathAnim); activeWorld.playLocationSound(deathPosition, defender.instance.instanceId, soundIds.npc.human.maleDeath, 5); const npcDetails = findNpc((defender as Npc).id); - if(!npcDetails.dropTable) { + if (!npcDetails.dropTable) { return; } - if(isPlayer(assailant)) { + if (isPlayer(assailant)) { const itemDrops = calculateNpcDrops(assailant, npcDetails); itemDrops.forEach(drop => { const droppedItem = findItem(drop.itemKey); @@ -156,16 +154,22 @@ export class Npc extends Actor { return; } - activeWorld.globalInstance.spawnWorldItem({ itemId: droppedItem.gameId, amount: drop.amount }, - deathPosition, { owner: assailant, expires: 300 }); - }) + activeWorld.globalInstance.spawnWorldItem({ itemId: droppedItem.gameId, amount: drop.amount }, deathPosition, { + owner: assailant, + expires: 300, + }); + }); } }); } public withinBounds(x: number, y: number): boolean { - return !(x > this.initialPosition.x + this.movementRadius || x < this.initialPosition.x - this.movementRadius - || y > this.initialPosition.y + this.movementRadius || y < this.initialPosition.y - this.movementRadius); + return !( + x > this.initialPosition.x + this.movementRadius || + x < this.initialPosition.x - this.movementRadius || + y > this.initialPosition.y + this.movementRadius || + y < this.initialPosition.y - this.movementRadius + ); } public kill(respawn: boolean = true): void { @@ -175,7 +179,7 @@ export class Npc extends Actor { clearInterval(this.randomMovementInterval); activeWorld.deregisterNpc(this); - if(respawn) { + if (respawn) { const npcDetails = findNpc(this.id); activeWorld.scheduleNpcRespawn(new Npc(npcDetails, this.npcSpawn)); } @@ -209,7 +213,7 @@ export class Npc extends Actor { * Whether or not the Npc can currently move. */ public canMove(): boolean { - if(this.metadata.following) { + if (this.metadata.following) { return false; } return this.updateFlags.faceActor === null && this.updateFlags.animation === null; @@ -244,7 +248,7 @@ export class Npc extends Actor { } public equals(other: Npc): boolean { - if(!other) { + if (!other) { return false; } @@ -254,7 +258,7 @@ export class Npc extends Actor { public set position(position: Position) { super.position = position; - if(this.quadtreeKey !== null) { + if (this.quadtreeKey !== null) { activeWorld.npcTree.remove(this.quadtreeKey); } @@ -304,32 +308,32 @@ export class Npc extends Actor { * @param player The player receiving the drop. * @param npcDetails The NpcDetails of the NPC that contains the DropTable data. */ -export function calculateNpcDrops(player: Player, npcDetails: NpcDetails): { itemKey: string, amount?: number }[] { - const itemDrops: { itemKey: string, amount?: number }[] = []; +export function calculateNpcDrops(player: Player, npcDetails: NpcDetails): { itemKey: string; amount?: number }[] { + const itemDrops: { itemKey: string; amount?: number }[] = []; const npcDropTable = npcDetails.dropTable; - if(!npcDropTable) { + if (!npcDropTable) { return itemDrops; } npcDropTable.forEach(drop => { let meetsQuestRequirements = true; - if(drop.questRequirement) { - meetsQuestRequirements = (player.getQuest(drop.questRequirement.questId).progress === drop.questRequirement.stage); + if (drop.questRequirement) { + meetsQuestRequirements = player.getQuest(drop.questRequirement.questId).progress === drop.questRequirement.stage; } drop.amount = drop.amount || 1; drop.amountMax = drop.amountMax || 1; - let odds: { numerator: number, denominator: number }; - if(drop.frequency === 'always') { + let odds: { numerator: number; denominator: number }; + if (drop.frequency === 'always') { odds = { numerator: 1, denominator: 1 }; } else { const dividedFrequency = drop.frequency.split('/'); odds = { numerator: Number(dividedFrequency[0]), denominator: Number(dividedFrequency[1]) }; } const randomNumber = getRandomInt(odds.denominator); - if(randomNumber === 1 && meetsQuestRequirements) { + if (randomNumber === 1 && meetsQuestRequirements) { const randomNumberOfItems = getRandomInt(drop.amountMax, drop.amount); - itemDrops.push({ itemKey: drop.itemKey, amount: randomNumberOfItems }) + itemDrops.push({ itemKey: drop.itemKey, amount: randomNumberOfItems }); } }); diff --git a/src/engine/world/actor/pathfinding.ts b/src/engine/world/actor/pathfinding.ts index b4bfb3f9b..afe4969af 100644 --- a/src/engine/world/actor/pathfinding.ts +++ b/src/engine/world/actor/pathfinding.ts @@ -1,30 +1,30 @@ +import { activeWorld } from '@engine/world'; import type { Actor } from '@engine/world/actor/actor'; -import { Position } from '../position'; -import type { Chunk } from '@engine/world/map/chunk'; -import { logger } from '@runejs/common'; +import { isPlayer } from '@engine/world/actor/util'; import type { WorldInstance } from '@engine/world/instances'; +import type { Chunk } from '@engine/world/map/chunk'; import type { Tile } from '@engine/world/map/chunk-manager'; -import { activeWorld } from '@engine/world'; -import { isPlayer } from '@engine/world/actor/util'; - +import { logger } from '@runejs/common'; +import { Position } from '../position'; class Point { - private _parent: Point | null = null; private _cost: number = 0; - public constructor(private readonly _x: number, private readonly _y: number) { - } + public constructor( + private readonly _x: number, + private readonly _y: number, + ) {} public equals(point: Point | null): boolean { if (point === null) { return false; } - if(this._cost === point._cost) { - if(this._parent === null && point._parent !== null) { + if (this._cost === point._cost) { + if (this._parent === null && point._parent !== null) { return false; - } else if(this._parent !== null && !this._parent.equals(point._parent)) { + } else if (this._parent !== null && !this._parent.equals(point._parent)) { return false; } @@ -65,25 +65,23 @@ export interface PathingOptions { } export class Pathfinding { - public stopped = false; private currentPoint: Point; private points: Point[][]; private closedPoints = new Set(); private openPoints = new Set(); - public constructor(private actor: Actor) { - } + public constructor(private actor: Actor) {} public walkTo(position: Position, options: PathingOptions): void { - if(!options.pathingSearchRadius) { + if (!options.pathingSearchRadius) { options.pathingSearchRadius = 16; } try { const path = this.pathTo(position.x, position.y, options.pathingSearchRadius); - if(!path) { + if (!path) { return; } @@ -92,14 +90,14 @@ export class Pathfinding { walkingQueue.clear(); walkingQueue.valid = true; - if(options.ignoreDestination) { + if (options.ignoreDestination) { path.splice(path.length - 1, 1); } - for(const point of path) { + for (const point of path) { walkingQueue.add(point.x, point.y); } - } catch(error) { + } catch (error) { logger.error(error); } } @@ -112,15 +110,13 @@ export class Pathfinding { const highestY = position.y + searchRadius; const tiles: Tile[] = []; - for(let x = lowestX; x < highestX; x++) { - for(let y = lowestY; y < highestY; y++) { + for (let x = lowestX; x < highestX; x++) { + for (let y = lowestY; y < highestY; y++) { tiles.push(activeWorld.chunkManager.getTile(new Position(x, y, this.actor.position.level))); } } - return Object.fromEntries( - tiles.map(tile => [ `${tile.x},${tile.y}`, tile ]) - ); + return Object.fromEntries(tiles.map(tile => [`${tile.x},${tile.y}`, tile])); } public pathTo(destinationX: number, destinationY: number, searchRadius: number = 16): Point[] | null { @@ -130,7 +126,7 @@ export class Pathfinding { const highestX = position.x + searchRadius; const highestY = position.y + searchRadius; - if(destinationX < lowestX || destinationX > highestX || destinationY < lowestY || destinationY > highestY) { + if (destinationX < lowestX || destinationX > highestX || destinationY < lowestY || destinationY > highestY) { throw new Error(`Out of range.`); } @@ -141,14 +137,14 @@ export class Pathfinding { const pointLen = searchRadius * 2; - if(pointLen <= 0) { + if (pointLen <= 0) { throw new Error(`Why is your search radius zero?`); } this.points = [...Array(pointLen)].map(e => Array(pointLen)); - for(let x = 0; x < pointLen; x++) { - for(let y = 0; y < pointLen; y++) { + for (let x = 0; x < pointLen; x++) { + for (let y = 0; y < pointLen; y++) { this.points[x][y] = new Point(lowestX + x, lowestY + y); } } @@ -158,14 +154,14 @@ export class Pathfinding { this.closedPoints = new Set(); this.openPoints.add(this.points[startingIndexX][startingIndexY]); - while(this.openPoints.size > 0) { - if(this.stopped) { + while (this.openPoints.size > 0) { + if (this.stopped) { return null; } const bestPoint = this.calculateBestPoint(); - if(!bestPoint || bestPoint.equals(this.points[destinationIndexX][destinationIndexY])) { + if (!bestPoint || bestPoint.equals(this.points[destinationIndexX][destinationIndexY])) { break; } @@ -180,63 +176,61 @@ export class Pathfinding { const indexY = y - lowestY; // North-West - if(indexX > 0 && this.points[indexX - 1] && indexY < this.points[indexX - 1].length - 1) { - if(this.canPathDiagonally(x, y, new Position(x - 1, y + 1, level), -1, 1, - 0x1280138, 0x1280108, 0x1280120)) { + if (indexX > 0 && this.points[indexX - 1] && indexY < this.points[indexX - 1].length - 1) { + if (this.canPathDiagonally(x, y, new Position(x - 1, y + 1, level), -1, 1, 0x1280138, 0x1280108, 0x1280120)) { this.calculateCost(this.points[indexX - 1][indexY + 1]); } } // North-East - if(indexX < this.points.length - 1 && this.points[indexX + 1] && indexY < this.points[indexX + 1].length - 1) { - if(this.canPathDiagonally(x, y, new Position(x + 1, y + 1, level), 1, 1, - 0x12801e0, 0x1280180, 0x1280120)) { + if (indexX < this.points.length - 1 && this.points[indexX + 1] && indexY < this.points[indexX + 1].length - 1) { + if (this.canPathDiagonally(x, y, new Position(x + 1, y + 1, level), 1, 1, 0x12801e0, 0x1280180, 0x1280120)) { this.calculateCost(this.points[indexX + 1][indexY + 1]); } } // South-West - if(indexX > 0 && indexY > 0 && this.points[indexX - 1]) { - if(this.canPathDiagonally(x, y, - new Position(x - 1, y - 1, level), -1, -1, - 0x128010e, 0x1280108, 0x1280102)) { + if (indexX > 0 && indexY > 0 && this.points[indexX - 1]) { + if (this.canPathDiagonally(x, y, new Position(x - 1, y - 1, level), -1, -1, 0x128010e, 0x1280108, 0x1280102)) { this.calculateCost(this.points[indexX - 1][indexY - 1]); } } // South-East - if(indexX < this.points.length - 1 && indexY > 0 && this.points[indexX + 1]) { - if(this.canPathDiagonally(x, y, new Position(x + 1, y - 1, level), 1, -1, - 0x1280183, 0x1280180, 0x1280102)) { + if (indexX < this.points.length - 1 && indexY > 0 && this.points[indexX + 1]) { + if (this.canPathDiagonally(x, y, new Position(x + 1, y - 1, level), 1, -1, 0x1280183, 0x1280180, 0x1280102)) { this.calculateCost(this.points[indexX + 1][indexY - 1]); } } // West - if(indexX > 0 && this.canPathNSEW(new Position(x - 1, y, level), 0x1280108)) { + if (indexX > 0 && this.canPathNSEW(new Position(x - 1, y, level), 0x1280108)) { this.calculateCost(this.points[indexX - 1][indexY]); } // East - if(indexX < this.points.length - 1 && this.canPathNSEW(new Position(x + 1, y, level), 0x1280180)) { + if (indexX < this.points.length - 1 && this.canPathNSEW(new Position(x + 1, y, level), 0x1280180)) { this.calculateCost(this.points[indexX + 1][indexY]); } // South - if(indexY > 0 && this.canPathNSEW(new Position(x, y - 1, level), 0x1280102)) { + if (indexY > 0 && this.canPathNSEW(new Position(x, y - 1, level), 0x1280102)) { this.calculateCost(this.points[indexX][indexY - 1]); } // North - if(this.points[indexX] && indexY < this.points[indexX].length - 1 && - this.canPathNSEW(new Position(x, y + 1, level), 0x1280120)) { + if ( + this.points[indexX] && + indexY < this.points[indexX].length - 1 && + this.canPathNSEW(new Position(x, y + 1, level), 0x1280120) + ) { this.calculateCost(this.points[indexX][indexY + 1]); } } const destinationPoint = this.points[destinationIndexX][destinationIndexY]; - if(!destinationPoint || !destinationPoint.parent) { + if (!destinationPoint || !destinationPoint.parent) { // throw new Error(`Unable to find destination point.`); return null; } @@ -247,7 +241,7 @@ export class Pathfinding { let iterations = 0; do { - if(this.stopped) { + if (this.stopped) { return null; } @@ -255,14 +249,14 @@ export class Pathfinding { point = point.parent; iterations++; - if(iterations > 1000) { + if (iterations > 1000) { throw new Error(`Path iteration overflow, path can not be found.`); } - if(point === null) { + if (point === null) { break; } - } while(!point.equals(this.points[startingIndexX][startingIndexY])); + } while (!point.equals(this.points[startingIndexX][startingIndexY])); return path.reverse(); } @@ -271,7 +265,7 @@ export class Pathfinding { const destinationChunk: Chunk = activeWorld.chunkManager.getChunkForWorldPosition(destination); const tile: Tile = activeWorld.chunkManager.getTile(destination); - if(tile?.blocked) { + if (tile?.blocked) { return false; } @@ -281,61 +275,117 @@ export class Pathfinding { const destinationLocalY: number = destination.y - destinationChunk.collisionMap.insetY; // West - if(destination.x < initialX && destination.y == initialY) { - if(!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280108)) { + if (destination.x < initialX && destination.y == initialY) { + if (!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280108)) { return false; } } // East - if(destination.x > initialX && destination.y == initialY) { - if(!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280180)) { + if (destination.x > initialX && destination.y == initialY) { + if (!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280180)) { return false; } } // South - if(destination.y < initialY && destination.x == initialX) { - if(!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280102)) { + if (destination.y < initialY && destination.x == initialX) { + if (!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280102)) { return false; } } // North - if(destination.y > initialY && destination.x == initialX) { - if(!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280120)) { + if (destination.y > initialY && destination.x == initialX) { + if (!this.movementPermitted(this.instance, destinationChunk, destinationLocalX, destinationLocalY, 0x1280120)) { return false; } } // South-West - if(destination.x < initialX && destination.y < initialY) { - if(!this.diagonalMovementPermitted(this.instance, origin, destinationChunk, destinationLocalX, destinationLocalY, initialX, initialY, -1, -1, - 0x128010e, 0x1280108, 0x1280102)) { + if (destination.x < initialX && destination.y < initialY) { + if ( + !this.diagonalMovementPermitted( + this.instance, + origin, + destinationChunk, + destinationLocalX, + destinationLocalY, + initialX, + initialY, + -1, + -1, + 0x128010e, + 0x1280108, + 0x1280102, + ) + ) { return false; } } // South-East - if(destination.x > initialX && destination.y < initialY) { - if(!this.diagonalMovementPermitted(this.instance, origin, destinationChunk, destinationLocalX, destinationLocalY, initialX, initialY, 1, -1, - 0x1280183, 0x1280180, 0x1280102)) { + if (destination.x > initialX && destination.y < initialY) { + if ( + !this.diagonalMovementPermitted( + this.instance, + origin, + destinationChunk, + destinationLocalX, + destinationLocalY, + initialX, + initialY, + 1, + -1, + 0x1280183, + 0x1280180, + 0x1280102, + ) + ) { return false; } } // North-West - if(destination.x < initialX && destination.y > initialY) { - if(!this.diagonalMovementPermitted(this.instance, origin, destinationChunk, destinationLocalX, destinationLocalY, initialX, initialY, -1, 1, - 0x1280138, 0x1280108, 0x1280120)) { + if (destination.x < initialX && destination.y > initialY) { + if ( + !this.diagonalMovementPermitted( + this.instance, + origin, + destinationChunk, + destinationLocalX, + destinationLocalY, + initialX, + initialY, + -1, + 1, + 0x1280138, + 0x1280108, + 0x1280120, + ) + ) { return false; } } // North-East - if(destination.x > initialX && destination.y > initialY) { - if(!this.diagonalMovementPermitted(this.instance, origin, destinationChunk, destinationLocalX, destinationLocalY, initialX, initialY, 1, 1, - 0x12801e0, 0x1280180, 0x1280120)) { + if (destination.x > initialX && destination.y > initialY) { + if ( + !this.diagonalMovementPermitted( + this.instance, + origin, + destinationChunk, + destinationLocalX, + destinationLocalY, + initialX, + initialY, + 1, + 1, + 0x12801e0, + 0x1280180, + 0x1280120, + ) + ) { return false; } } @@ -343,8 +393,15 @@ export class Pathfinding { return true; } - public movementPermitted(instance: WorldInstance, globalChunk: Chunk, destinationLocalX: number, destinationLocalY: number, i: number): boolean { - const instancedAdjacency = instance.getInstancedChunk(globalChunk.position.x, globalChunk.position.y, globalChunk.position.level).collisionMap.adjacency; + public movementPermitted( + instance: WorldInstance, + globalChunk: Chunk, + destinationLocalX: number, + destinationLocalY: number, + i: number, + ): boolean { + const instancedAdjacency = instance.getInstancedChunk(globalChunk.position.x, globalChunk.position.y, globalChunk.position.level) + .collisionMap.adjacency; const globalAdjacency = globalChunk.collisionMap.adjacency; try { @@ -352,36 +409,46 @@ export class Pathfinding { const instancedTileFlags = instancedAdjacencyForTile === null ? null : instancedAdjacencyForTile & i; - const globalAdjacencyForTile = - globalAdjacency[destinationLocalX][destinationLocalY]; + const globalAdjacencyForTile = globalAdjacency[destinationLocalX][destinationLocalY]; - const globalTileFlags = - globalAdjacencyForTile === null - ? null - : globalAdjacencyForTile & i; + const globalTileFlags = globalAdjacencyForTile === null ? null : globalAdjacencyForTile & i; return instancedTileFlags === null ? globalTileFlags === 0 : instancedTileFlags === 0; - } catch(error) { + } catch (error) { logger.error(`Unable to calculate movement permission for local coordinates ${destinationLocalX},${destinationLocalY}.`); return false; } } - public diagonalMovementPermitted(instance: WorldInstance, origin: Position, destinationGlobalChunk: Chunk, destinationLocalX: number, destinationLocalY: number, - initialX: number, initialY: number, offsetX: number, offsetY: number, destMask: number, cornerMask1: number, cornerMask2: number): boolean { + public diagonalMovementPermitted( + instance: WorldInstance, + origin: Position, + destinationGlobalChunk: Chunk, + destinationLocalX: number, + destinationLocalY: number, + initialX: number, + initialY: number, + offsetX: number, + offsetY: number, + destMask: number, + cornerMask1: number, + cornerMask2: number, + ): boolean { const corner1 = this.findLocalCornerChunk(initialX + offsetX, initialY, origin); const corner2 = this.findLocalCornerChunk(initialX, initialY + offsetY, origin); - return this.movementPermitted(instance, destinationGlobalChunk, destinationLocalX, destinationLocalY, destMask) && + return ( + this.movementPermitted(instance, destinationGlobalChunk, destinationLocalX, destinationLocalY, destMask) && this.movementPermitted(instance, corner1.chunk, corner1.localX, corner1.localY, cornerMask1) && - this.movementPermitted(instance, corner2.chunk, corner2.localX, corner2.localY, cornerMask2); + this.movementPermitted(instance, corner2.chunk, corner2.localX, corner2.localY, cornerMask2) + ); } - public findLocalCornerChunk(cornerX: number, cornerY: number, origin: Position): { localX: number, localY: number, chunk: Chunk } { + public findLocalCornerChunk(cornerX: number, cornerY: number, origin: Position): { localX: number; localY: number; chunk: Chunk } { const cornerPosition: Position = new Position(cornerX, cornerY, origin.level + 1); let cornerChunk: Chunk = activeWorld.chunkManager.getChunkForWorldPosition(cornerPosition); const tileAbove: Tile = activeWorld.chunkManager.getTile(cornerPosition); - if(!tileAbove?.bridge) { + if (!tileAbove?.bridge) { cornerPosition.level = cornerPosition.level - 1; cornerChunk = activeWorld.chunkManager.getChunkForWorldPosition(cornerPosition); } @@ -392,18 +459,18 @@ export class Pathfinding { } private calculateCost(point: Point): void { - if(!this.currentPoint || !point) { + if (!this.currentPoint || !point) { return; } const nextStepCost = this.currentPoint.cost + this.calculateCostBetween(this.currentPoint, point); - if(nextStepCost < point.cost) { + if (nextStepCost < point.cost) { this.openPoints.delete(point); this.closedPoints.delete(point); } - if(!this.openPoints.has(point) && !this.closedPoints.has(point)) { + if (!this.openPoints.has(point) && !this.closedPoints.has(point)) { point.parent = this.currentPoint; point.cost = nextStepCost; this.openPoints.add(point); @@ -420,9 +487,9 @@ export class Pathfinding { let bestPoint: Point | null = null; this.openPoints.forEach(point => { - if(!bestPoint) { + if (!bestPoint) { bestPoint = point; - } else if(point.cost < bestPoint.cost) { + } else if (point.cost < bestPoint.cost) { bestPoint = point; } }); @@ -437,17 +504,36 @@ export class Pathfinding { return this.movementPermitted(this.instance, chunk, destinationLocalX, destinationLocalY, i); } - private canPathDiagonally(originX: number, originY: number, position: Position, offsetX: number, offsetY: number, - destMask: number, cornerMask1: number, cornerMask2: number): boolean { + private canPathDiagonally( + originX: number, + originY: number, + position: Position, + offsetX: number, + offsetY: number, + destMask: number, + cornerMask1: number, + cornerMask2: number, + ): boolean { const chunk = activeWorld.chunkManager.getChunkForWorldPosition(position); const destinationLocalX: number = position.x - chunk.collisionMap.insetX; const destinationLocalY: number = position.y - chunk.collisionMap.insetY; - return this.diagonalMovementPermitted(this.instance, position, chunk, destinationLocalX, destinationLocalY, - originX, originY, offsetX, offsetY, destMask, cornerMask1, cornerMask2); + return this.diagonalMovementPermitted( + this.instance, + position, + chunk, + destinationLocalX, + destinationLocalY, + originX, + originY, + offsetX, + offsetY, + destMask, + cornerMask1, + cornerMask2, + ); } private get instance(): WorldInstance { return isPlayer(this.actor) ? this.actor.instance : activeWorld.globalInstance; } - } diff --git a/src/engine/world/actor/player/achievements.ts b/src/engine/world/actor/player/achievements.ts index fc35a9ffd..93ee5b473 100644 --- a/src/engine/world/actor/player/achievements.ts +++ b/src/engine/world/actor/player/achievements.ts @@ -1,14 +1,14 @@ import type { Player } from '@engine/world/actor/player/player'; -import { serverConfig } from '@server/game/game-server'; import { gfxIds } from '@engine/world/config/gfx-ids'; +import { serverConfig } from '@server/game/game-server'; export const achievementSeries = { lumbridge: { - name: 'Lumbridge' + name: 'Lumbridge', }, varrock: { - name: 'Varrock' - } + name: 'Varrock', + }, }; export enum AchievementSeries { @@ -30,36 +30,37 @@ export const Achievements: { [key: string]: Achievement } = { name: 'Welcome!', description: 'Talk to Hans.', longDescription: `Speak with Hans in the Lumbridge Castle's courtyard.`, - series: AchievementSeries.LUMBRIDGE + series: AchievementSeries.LUMBRIDGE, }, BURY_BONES: { id: 'bury-bones', name: 'Grave Digger', description: 'Bury the bones of the dead.', longDescription: `Bury the remains of a deceased enemy.`, - series: AchievementSeries.LUMBRIDGE - } + series: AchievementSeries.LUMBRIDGE, + }, }; export function giveAchievement(achievement: Achievement, player: Player): boolean { - if(!serverConfig.giveAchievements) { + if (!serverConfig.giveAchievements) { return false; } - if(hasAchievement(achievement, player)) { + if (hasAchievement(achievement, player)) { return false; } player.achievements.push(achievement.id); player.playGraphics({ id: gfxIds.levelUpFireworks, delay: 0, height: 125 }); - player.sendMessage(`You've completed an Achievement in the ` + - `${ achievementSeries[achievement.series].name } series!`); - player.sendMessage(`${ achievement.name } - ${ achievement.description }`); + player.sendMessage( + `You've completed an Achievement in the ` + `${achievementSeries[achievement.series].name} series!`, + ); + player.sendMessage(`${achievement.name} - ${achievement.description}`); return true; } export function hasAchievement(achievement: Achievement, player: Player): boolean { - if(!player.achievements || player.achievements.length === 0) { + if (!player.achievements || player.achievements.length === 0) { return false; } diff --git a/src/engine/world/actor/player/attack.ts b/src/engine/world/actor/player/attack.ts index 25fd0e5d1..bec7e32fe 100644 --- a/src/engine/world/actor/player/attack.ts +++ b/src/engine/world/actor/player/attack.ts @@ -2,10 +2,10 @@ export class Attack { damageType: AttackDamageType; - attackRoll: number =0; + attackRoll: number = 0; defenseRoll: number = 0; - hitChance: number =0; - damage: number =0; + hitChance: number = 0; + damage: number = 0; maximumHit: number; } @@ -14,5 +14,5 @@ export enum AttackDamageType { Slash, Crush, Magic, - Range -} \ No newline at end of file + Range, +} diff --git a/src/engine/world/actor/player/cutscenes.ts b/src/engine/world/actor/player/cutscenes.ts index 59ca53538..792909a22 100644 --- a/src/engine/world/actor/player/cutscenes.ts +++ b/src/engine/world/actor/player/cutscenes.ts @@ -1,7 +1,6 @@ import type { Player } from '@engine/world/actor/player/player'; import { Position } from '@engine/world/position'; - /** * Various camera options for cutscenes. */ @@ -18,12 +17,10 @@ export interface CameraOptions { lookAcceleration?: number; } - /** * Controls a game cutscene for a specific player. */ export class Cutscene { - public readonly player: Player; private _cameraX: number; private _cameraY: number; @@ -39,7 +36,7 @@ export class Cutscene { public constructor(player: Player, options?: CameraOptions) { this.player = player; - if(options) { + if (options) { this.setCamera(options); } } @@ -49,16 +46,24 @@ export class Cutscene { * @param options The camera options to use. */ public setCamera(options: CameraOptions): void { - const { cameraX, cameraY, cameraHeight, cameraMovementSpeed, cameraAcceleration, - lookX, lookY, lookHeight, lookMovementSpeed, lookAcceleration } = options; - - if(cameraX && cameraY) { - this.snapCameraTo(cameraX, cameraY, cameraHeight || 400, - cameraMovementSpeed || 0, cameraAcceleration || 100); + const { + cameraX, + cameraY, + cameraHeight, + cameraMovementSpeed, + cameraAcceleration, + lookX, + lookY, + lookHeight, + lookMovementSpeed, + lookAcceleration, + } = options; + + if (cameraX && cameraY) { + this.snapCameraTo(cameraX, cameraY, cameraHeight || 400, cameraMovementSpeed || 0, cameraAcceleration || 100); } - if(lookX && lookY) { - this.lookAt(lookX, lookY, lookHeight || 400, - lookMovementSpeed || 0, lookAcceleration || 100); + if (lookX && lookY) { + this.lookAt(lookX, lookY, lookHeight || 400, lookMovementSpeed || 0, lookAcceleration || 100); } } @@ -70,8 +75,13 @@ export class Cutscene { * @param movementSpeed The general speed of the camera movement. Defaults to 0 (immediate). * @param acceleration The acceleration speed of the camera movement. Defaults to 100 (instantaneous). */ - public snapCameraTo(cameraX: number, cameraY: number, height: number = 400, movementSpeed: number = 0, - acceleration: number = 100): void { + public snapCameraTo( + cameraX: number, + cameraY: number, + height: number = 400, + movementSpeed: number = 0, + acceleration: number = 100, + ): void { this._cameraX = cameraX; this._cameraY = cameraY; this._cameraHeight = height; @@ -88,8 +98,7 @@ export class Cutscene { * @param movementSpeed The general speed of the camera movement. Defaults to 0 (immediate). * @param acceleration The acceleration speed of the camera movement. Defaults to 100 (instantaneous). */ - public lookAt(lookX: number, lookY: number, height: number = 400, movementSpeed: number = 0, - acceleration: number = 100): void { + public lookAt(lookX: number, lookY: number, height: number = 400, movementSpeed: number = 0, acceleration: number = 100): void { this._lookX = lookX; this._lookY = lookY; this._lookHeight = height; @@ -106,7 +115,6 @@ export class Cutscene { this.player.cutscene = null; } - public get cameraX(): number { return this._cameraX; } diff --git a/src/engine/world/actor/player/dialogue-action.ts b/src/engine/world/actor/player/dialogue-action.ts index 78678ae95..d74908636 100644 --- a/src/engine/world/actor/player/dialogue-action.ts +++ b/src/engine/world/actor/player/dialogue-action.ts @@ -1,24 +1,24 @@ +import type { Npc } from '@engine/world/actor/npc'; import type { Player } from '@engine/world/actor/player/player'; import { filestore } from '@server/game/game-server'; -import type { Npc } from '@engine/world/actor/npc'; export const dialogueWidgetIds = { - PLAYER: [ 64, 65, 66, 67 ], - NPC: [ 241, 242, 243, 244 ], - OPTIONS: [ 228, 230, 232, 234 ], - TEXT: [ 210, 211, 212, 213, 214 ] + PLAYER: [64, 65, 66, 67], + NPC: [241, 242, 243, 244], + OPTIONS: [228, 230, 232, 234], + TEXT: [210, 211, 212, 213, 214], }; -type LineConstraint = [ number, number ]; +type LineConstraint = [number, number]; /** * Min -> max lines for a specific dialogue type. */ const lineConstraints: { [key: string]: LineConstraint } = { - PLAYER: [ 1, 4 ], - NPC: [ 1, 4 ], - OPTIONS: [ 2, 5 ], - TEXT: [ 1, 5 ] + PLAYER: [1, 4], + NPC: [1, 4], + OPTIONS: [2, 5], + TEXT: [1, 5], }; export enum DialogueEmote { @@ -51,7 +51,7 @@ export enum DialogueEmote { ANGRY_1 = 614, ANGRY_2 = 615, ANGRY_3 = 616, - ANGRY_4 = 617 + ANGRY_4 = 617, } export type DialogueType = 'PLAYER' | 'NPC' | 'OPTIONS' | 'TEXT'; @@ -67,11 +67,9 @@ export interface DialogueOptions { // @DEPRECATED export class DialogueAction { - private _action: number | null = null; - public constructor(private readonly p: Player) { - } + public constructor(private readonly p: Player) {} public async player(emote: DialogueEmote, lines: string[]): Promise { return this.dialogue({ emote, lines, type: 'PLAYER' }); @@ -86,35 +84,35 @@ export class DialogueAction { } public async dialogue(options: DialogueOptions): Promise { - if(options.lines.length < lineConstraints[options.type][0] || options.lines.length > lineConstraints[options.type][1]) { + if (options.lines.length < lineConstraints[options.type][0] || options.lines.length > lineConstraints[options.type][1]) { throw new Error('Invalid line length.'); } - if(options.type === 'NPC' && options.npc === undefined) { + if (options.type === 'NPC' && options.npc === undefined) { throw new Error('NPC not supplied.'); } this._action = null; let widgetIndex = options.lines.length - 1; - if(options.type === 'OPTIONS') { + if (options.type === 'OPTIONS') { widgetIndex--; } const widgetId = dialogueWidgetIds[options.type][widgetIndex]; - if(widgetId === undefined || widgetId === null || widgetId === -1) { + if (widgetId === undefined || widgetId === null || widgetId === -1) { return Promise.resolve(this); } let textOffset = 0; - if(options.type === 'PLAYER' || options.type === 'NPC') { - if(!options.emote) { + if (options.type === 'PLAYER' || options.type === 'NPC') { + if (!options.emote) { options.emote = DialogueEmote.DEFAULT; } - if(options.type === 'NPC') { + if (options.type === 'NPC') { const npc = options.npc; if (npc === undefined) { @@ -130,28 +128,28 @@ export class DialogueAction { this.p.outgoingPackets.setWidgetNpcHead(widgetId, 0, npc); this.p.outgoingPackets.updateWidgetString(widgetId, 1, cacheNpc.name || 'Unknown'); - } else if(options.type === 'PLAYER') { + } else if (options.type === 'PLAYER') { this.p.outgoingPackets.setWidgetPlayerHead(widgetId, 0); this.p.outgoingPackets.updateWidgetString(widgetId, 1, this.p.username); } this.p.outgoingPackets.playWidgetAnimation(widgetId, 0, options.emote); textOffset = 2; - } else if(options.type === 'OPTIONS') { + } else if (options.type === 'OPTIONS') { this.p.outgoingPackets.updateWidgetString(widgetId, 0, options.title || 'No Title'); textOffset = 1; - } else if(options.type === 'TEXT') { + } else if (options.type === 'TEXT') { textOffset = 0; } - for(let i = 0; i < options.lines.length; i++) { + for (let i = 0; i < options.lines.length; i++) { this.p.outgoingPackets.updateWidgetString(widgetId, textOffset + i, options.lines[i]); } return new Promise((resolve, reject) => { this.p.interfaceState.openWidget(widgetId, { - slot: 'chatbox' - }) + slot: 'chatbox', + }); const sub = this.p.interfaceState.closed.subscribe(action => { sub.unsubscribe(); this._action = action?.data ?? null; @@ -174,7 +172,7 @@ export class DialogueAction { } export const dialogueAction = async (player: Player, options?: DialogueOptions): Promise => { - if(options) { + if (options) { return new DialogueAction(player).dialogue(options); } else { return Promise.resolve(new DialogueAction(player)); diff --git a/src/engine/world/actor/player/metadata.ts b/src/engine/world/actor/player/metadata.ts index 0b79fb279..103fdbf8b 100644 --- a/src/engine/world/actor/player/metadata.ts +++ b/src/engine/world/actor/player/metadata.ts @@ -1,7 +1,7 @@ -import type { Subject, Subscription } from 'rxjs'; +import type { Chunk } from '@engine/world/map/chunk'; import type { Position } from '@engine/world/position'; import type { LandscapeObject } from '@runejs/filestore'; -import type { Chunk } from '@engine/world/map/chunk'; +import type { Subject, Subscription } from 'rxjs'; /** * The definition of the metadata directly available on a {@link Player}. @@ -113,5 +113,4 @@ export type PlayerMetadata = { * before the teleport animation finishes (it takes a few ticks). */ castingStationarySpell: boolean; - }; diff --git a/src/engine/world/actor/player/player-data.ts b/src/engine/world/actor/player/player-data.ts index 0a7ded01e..1aea295a9 100644 --- a/src/engine/world/actor/player/player-data.ts +++ b/src/engine/world/actor/player/player-data.ts @@ -1,12 +1,12 @@ -import type { Item } from '@engine/world/items/item'; import { existsSync, readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; +import type { PlayerQuest } from '@engine/config/quest-config'; +import { hasValueNotNull } from '@engine/util/data'; +import type { SkillValue } from '@engine/world/actor/skills'; +import type { Item } from '@engine/world/items/item'; +import { MusicPlayerLoopMode, MusicPlayerMode } from '@engine/world/sound/music'; import { logger } from '@runejs/common'; import type { Player } from './player'; -import type { SkillValue } from '@engine/world/actor/skills'; -import { hasValueNotNull } from '@engine/util/data'; -import type { PlayerQuest } from '@engine/config/quest-config'; -import { MusicPlayerMode, MusicPlayerLoopMode } from '@engine/world/sound/music'; export interface Appearance { gender: number; @@ -86,7 +86,7 @@ export const defaultAppearance = (): Appearance => { torsoColor: 0, legColor: 0, feetColor: 0, - skinColor: 0 + skinColor: 0, } as Appearance; }; @@ -99,12 +99,12 @@ export const validateSettings = (player: Player): void => { const newSettings = new PlayerSettings(); const newKeys = Object.keys(newSettings); - if(newKeys.length === existingKeys.length) { + if (newKeys.length === existingKeys.length) { return; } const missingKeys = newKeys.filter(key => existingKeys.indexOf(key) === -1); - for(const key of missingKeys) { + for (const key of missingKeys) { player.settings[key] = newSettings[key]; } }; @@ -119,16 +119,16 @@ export function savePlayerData(player: Player): boolean { position: { x: player.position.x, y: player.position.y, - level: player.position.level > 3 ? 0 : player.position.level + level: player.position.level > 3 ? 0 : player.position.level, }, lastLogin: { date: player.loginDate, - address: player.lastAddress + address: player.lastAddress, }, rights: player.rights.valueOf(), appearance: player.appearance, inventory: player.inventory.items, - bank: player.bank.items.filter((item) => { + bank: player.bank.items.filter(item => { return hasValueNotNull(item); }), equipment: player.equipment.items, @@ -139,13 +139,13 @@ export function savePlayerData(player: Player): boolean { musicTracks: player.musicTracks, achievements: player.achievements, friendsList: player.friendsList, - ignoreList: player.ignoreList + ignoreList: player.ignoreList, }; try { writeFileSync(filePath, JSON.stringify(playerSave, null, 4)); return true; - } catch(error) { + } catch (error) { logger.error(`Error saving player data for ${player.username}.`); return false; } @@ -161,23 +161,23 @@ export function loadPlayerSave(username: string): PlayerSave | null { const fileName = username.toLowerCase() + '.json'; const filePath = join('data/saves', fileName); - if(!existsSync(filePath)) { + if (!existsSync(filePath)) { return null; } const fileData = readFileSync(filePath, 'utf8'); - if(!fileData) { + if (!fileData) { return null; } try { const playerSave = JSON.parse(fileData) as PlayerSave; - if(playerSave?.position?.level > 3) { + if (playerSave?.position?.level > 3) { playerSave.position.level = 0; } return playerSave; - } catch(error) { + } catch (error) { logger.error(`Malformed player save data for ${username}.`); return null; } diff --git a/src/engine/world/actor/player/player.ts b/src/engine/world/actor/player/player.ts index fee8b98ff..b7ee8ef2f 100644 --- a/src/engine/world/actor/player/player.ts +++ b/src/engine/world/actor/player/player.ts @@ -1,20 +1,18 @@ -import type { AddressInfo, Socket } from 'net'; -import { v4 } from 'uuid'; -import { Subject } from 'rxjs'; import EventEmitter from 'events'; -import { logger } from '@runejs/common'; -import { Actor } from '../actor'; -import type { Cutscene } from './cutscenes'; -import type { SendMessageOptions } from './model'; -import { PlayerSyncTask } from './sync/player-sync-task' -import { NpcSyncTask } from './sync/npc-sync-task' -import { dialogue } from '../dialogue'; -import type { Npc } from '../npc'; -import type { SkillName } from '../skills'; -import type { PlayerMetadata } from './metadata'; +import type { AddressInfo, Socket } from 'net'; import type { PlayerCommandActionHook } from '@engine/action/pipe/player-command.action'; import { regionChangeActionFactory } from '@engine/action/pipe/region-change.action'; -import { widgets, findQuest, findMusicTrack, findItem, itemMap, npcIdMap, findNpc, findSongIdByRegionId, musicRegions } from '@engine/config/config-handler'; +import { + findItem, + findMusicTrack, + findNpc, + findQuest, + findSongIdByRegionId, + itemMap, + musicRegions, + npcIdMap, + widgets, +} from '@engine/config/config-handler'; import type { EquipmentSlot, ItemDetails } from '@engine/config/item-config'; import { equipmentIndex, getEquipmentSlot } from '@engine/config/item-config'; import type { NpcDetails } from '@engine/config/npc-config'; @@ -28,6 +26,8 @@ import { colors, hexToRgb, rgbTo16Bit } from '@engine/util/colors'; import { daysSinceLastLogin } from '@engine/util/time'; import { getVarbitMorphIndex } from '@engine/util/varbits'; import { activeWorld } from '@engine/world'; +import type { Appearance, PlayerSettings } from '@engine/world/actor/player/player-data'; +import { defaultAppearance, defaultSettings, loadPlayerSave, playerExists, savePlayerData } from '@engine/world/actor/player/player-data'; import { itemIds } from '@engine/world/config/item-ids'; import type { PlayerWidget } from '@engine/world/config/widget'; import { widgetScripts } from '@engine/world/config/widget'; @@ -40,30 +40,49 @@ import type { Chunk, ChunkUpdateItem } from '@engine/world/map/chunk'; import { Position } from '@engine/world/position'; import { MusicPlayerMode } from '@engine/world/sound/music'; import type { QuadtreeKey } from '@engine/world/world'; -import { serverConfig, filestore } from '@server/game/game-server'; -import type { Appearance, PlayerSettings } from '@engine/world/actor/player/player-data'; -import { savePlayerData, playerExists, loadPlayerSave, defaultAppearance, defaultSettings } from '@engine/world/actor/player/player-data'; - +import { logger } from '@runejs/common'; +import { filestore, serverConfig } from '@server/game/game-server'; +import { Subject } from 'rxjs'; +import { v4 } from 'uuid'; +import { Actor } from '../actor'; +import { dialogue } from '../dialogue'; +import type { Npc } from '../npc'; +import type { SkillName } from '../skills'; +import type { Cutscene } from './cutscenes'; +import type { PlayerMetadata } from './metadata'; +import type { SendMessageOptions } from './model'; +import { NpcSyncTask } from './sync/npc-sync-task'; +import { PlayerSyncTask } from './sync/player-sync-task'; -export const playerOptions: { option: string, index: number, placement: 'TOP' | 'BOTTOM' }[] = [ +export const playerOptions: { option: string; index: number; placement: 'TOP' | 'BOTTOM' }[] = [ { option: 'Yeet', index: 1, - placement: 'TOP' + placement: 'TOP', }, { option: 'Follow', index: 0, - placement: 'BOTTOM' - } + placement: 'BOTTOM', + }, ]; -export const defaultPlayerTabWidgets = () => ([ - -1, widgets.skillsTab, widgets.questTab, widgets.inventory.widgetId, - widgets.equipment.widgetId, widgets.prayerTab, widgets.standardSpellbookTab, null, - widgets.friendsList, widgets.ignoreList, widgets.logoutTab, widgets.settingsTab, widgets.emotesTab, - widgets.musicPlayerTab -]); +export const defaultPlayerTabWidgets = () => [ + -1, + widgets.skillsTab, + widgets.questTab, + widgets.inventory.widgetId, + widgets.equipment.widgetId, + widgets.prayerTab, + widgets.standardSpellbookTab, + null, + widgets.friendsList, + widgets.ignoreList, + widgets.logoutTab, + widgets.settingsTab, + widgets.emotesTab, + widgets.musicPlayerTab, +]; export enum SidebarTab { COMBAT, @@ -78,21 +97,19 @@ export enum SidebarTab { LOGOUT, SETTINGS, EMOTES, - MUSIC + MUSIC, } export enum Rights { ADMIN = 2, MOD = 1, - USER = 0 + USER = 0, } - /** * A player character within the game world. */ export class Player extends Actor { - public readonly clientUuid: number; public readonly username: string; public readonly passwordHash: string; @@ -108,7 +125,7 @@ export class Player extends Actor { public savedMetadata: { [key: string]: any } = {}; public sessionMetadata: { [key: string]: any } = {}; public quests: PlayerQuest[] = []; - public musicTracks: Array = [ 0, 400, 547, 321 ]; + public musicTracks: Array = [0, 400, 547, 321]; public achievements: string[] = []; public friendsList: string[] = []; public ignoreList: string[] = []; @@ -123,7 +140,7 @@ export class Player extends Actor { * * @author jameskmonger */ - public readonly metadata: (Actor['metadata'] & Partial) = {}; + public readonly metadata: Actor['metadata'] & Partial = {}; private readonly _socket: Socket; private readonly _inCipher: Isaac; @@ -142,8 +159,15 @@ export class Player extends Actor { private quadtreeKey: QuadtreeKey | null = null; private privateMessageIndex: number = 1; - - public constructor(socket: Socket, inCipher: Isaac, outCipher: Isaac, clientUuid: number, username: string, password: string, isLowDetail: boolean) { + public constructor( + socket: Socket, + inCipher: Isaac, + outCipher: Isaac, + clientUuid: number, + username: string, + password: string, + isLowDetail: boolean, + ) { super('player'); this._socket = socket; @@ -183,51 +207,78 @@ export class Player extends Actor { this.outgoingPackets.updateCurrentMapChunk(); this.outgoingPackets.chatboxMessage('Welcome to RuneJS.'); - this.skills.values.forEach((skill, index) => - this.outgoingPackets.updateSkill(index, this.skills.getLevel(index), skill.exp)); + this.skills.values.forEach((skill, index) => this.outgoingPackets.updateSkill(index, this.skills.getLevel(index), skill.exp)); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipment, this.equipment); - for(const item of this.equipment.items) { - if(item) { + for (const item of this.equipment.items) { + if (item) { await this.actionPipeline.call('equipment_change', this, item.itemId, 'EQUIP'); } } - if(this.firstTimePlayer) { - if(!serverConfig.tutorialEnabled) { + if (this.firstTimePlayer) { + if (!serverConfig.tutorialEnabled) { this.interfaceState.openWidget(widgets.characterDesign, { slot: 'screen', - multi: false + multi: false, }); } - } else if(serverConfig.showWelcome && (!serverConfig.tutorialEnabled || this.savedMetadata.tutorialComplete)) { + } else if (serverConfig.showWelcome && (!serverConfig.tutorialEnabled || this.savedMetadata.tutorialComplete)) { const daysSinceLogin = daysSinceLastLogin(this.loginDate); let loginDaysStr = ''; - if(daysSinceLogin <= 0) { + if (daysSinceLogin <= 0) { loginDaysStr = 'earlier today'; - } else if(daysSinceLogin === 1) { + } else if (daysSinceLogin === 1) { loginDaysStr = 'yesterday'; } else { loginDaysStr = daysSinceLogin + ' days ago'; } - this.outgoingPackets.updateWidgetString(widgets.welcomeScreenChildren.question, 1, `Want to help RuneJS improve?\\nSend us a pull request over on Github!`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 13, `You last logged in @red@${loginDaysStr}@bla@ from: @red@${this.lastAddress}`); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreenChildren.question, + 1, + `Want to help RuneJS improve?\\nSend us a pull request over on Github!`, + ); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 13, + `You last logged in @red@${loginDaysStr}@bla@ from: @red@${this.lastAddress}`, + ); this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 16, `You have @yel@0 unread messages\\nin your message centre.`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 14, `\\nYou have not yet set any recovery questions.\\nIt is @lre@strongly@yel@ recommended that you do so.\\n\\nIf you don't you will be @lre@unable to recover your\\n@lre@password@yel@ if you forget it, or it is stolen.`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 22, `To change your recovery questions:\\n1) Logout and return to the frontpage of this website.\\n2) Choose 'Set new recovery questions'.`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 17, `\\nYou do not have a Bank PIN.\\nPlease visit a bank if you would like one.`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 21, `To start a subscripton:\\n1) Logout and return to the frontpage of this website.\\n2) Choose 'Start a new subscription'`); - this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 19, `You are not a member.\\n\\nChoose to subscribe and\\nyou'll get loads of extra\\nbenefits and features.`); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 14, + `\\nYou have not yet set any recovery questions.\\nIt is @lre@strongly@yel@ recommended that you do so.\\n\\nIf you don't you will be @lre@unable to recover your\\n@lre@password@yel@ if you forget it, or it is stolen.`, + ); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 22, + `To change your recovery questions:\\n1) Logout and return to the frontpage of this website.\\n2) Choose 'Set new recovery questions'.`, + ); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 17, + `\\nYou do not have a Bank PIN.\\nPlease visit a bank if you would like one.`, + ); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 21, + `To start a subscripton:\\n1) Logout and return to the frontpage of this website.\\n2) Choose 'Start a new subscription'`, + ); + this.outgoingPackets.updateWidgetString( + widgets.welcomeScreen, + 19, + `You are not a member.\\n\\nChoose to subscribe and\\nyou'll get loads of extra\\nbenefits and features.`, + ); this.interfaceState.openWidget(widgets.welcomeScreen, { slot: 'full', - containerId: widgets.welcomeScreenChildren.question + containerId: widgets.welcomeScreenChildren.question, }); } - for(const playerOption of playerOptions) { + for (const playerOption of playerOptions) { this.outgoingPackets.updatePlayerOption(playerOption.option, playerOption.index, playerOption.placement); } @@ -237,22 +288,22 @@ export class Player extends Actor { this.updateMusicTab(); this.inventory.containerUpdated.subscribe(event => this.inventoryUpdated(event)); - this.playerEvents.on('exp', (amt) => { + this.playerEvents.on('exp', amt => { logger.info(`Player should have been awarded ${amt} exp if this was hooked up.`); }); this.actionsCancelled.subscribe(type => { let closeWidget: boolean; - if(type === 'manual-movement' || type === 'pathing-movement') { + if (type === 'manual-movement' || type === 'pathing-movement') { closeWidget = true; - } else if(type === 'keep-widgets-open' || type === 'button' || type === 'widget') { + } else if (type === 'keep-widgets-open' || type === 'button' || type === 'widget') { closeWidget = false; } else { closeWidget = true; } - if(closeWidget) { + if (closeWidget) { this.interfaceState.closeAllSlots(); } }); @@ -260,7 +311,7 @@ export class Player extends Actor { this._loginDate = new Date(); this._lastAddress = (this._socket?.address() as AddressInfo)?.address || '127.0.0.1'; - if(this.rights === Rights.ADMIN) { + if (this.rights === Rights.ADMIN) { this.sendCommandList(actionHookMap.player_command as PlayerCommandActionHook[]); } this.outgoingPackets.resetAllClientConfigs(); @@ -269,7 +320,7 @@ export class Player extends Actor { activeWorld.spawnWorldItems(this); - if(!this.metadata.customMap) { + if (!this.metadata.customMap) { this.chunkChanged(playerChunk); } @@ -278,11 +329,11 @@ export class Player extends Actor { } public logout(): void { - if(!this.active) { + if (!this.active) { return; } - if(this.position.level > 3) { + if (this.position.level > 3) { this.position.level = 0; } @@ -318,7 +369,7 @@ export class Player extends Actor { } public addFriend(friendName: string): boolean { - if(!playerExists(friendName)) { + if (!playerExists(friendName)) { return false; } @@ -330,7 +381,7 @@ export class Player extends Actor { public removeFriend(friendName: string): boolean { friendName = friendName.toLowerCase(); const index = this.friendsList.findIndex(friend => friend === friendName); - if(index === -1) { + if (index === -1) { return false; } @@ -339,7 +390,7 @@ export class Player extends Actor { } public addIgnoredPlayer(playerName: string): boolean { - if(!playerExists(playerName)) { + if (!playerExists(playerName)) { return false; } @@ -347,7 +398,7 @@ export class Player extends Actor { const index = this.ignoreList.findIndex(ignoredPlayer => ignoredPlayer === playerName); - if(index !== -1) { + if (index !== -1) { return false; } @@ -359,7 +410,7 @@ export class Player extends Actor { public removeIgnoredPlayer(playerName: string): boolean { playerName = playerName.toLowerCase(); const index = this.ignoreList.findIndex(ignoredPlayer => ignoredPlayer === playerName); - if(index === -1) { + if (index === -1) { return false; } @@ -377,7 +428,7 @@ export class Player extends Actor { */ public chunkChanged(chunk: Chunk): void { const nearbyChunks = activeWorld.chunkManager.getSurroundingChunks(chunk); - if(this._nearbyChunks.length === 0) { + if (this._nearbyChunks.length === 0) { this.sendChunkUpdates(nearbyChunks); } else { const newChunks = nearbyChunks.filter(c1 => this._nearbyChunks.findIndex(c2 => c1.equals(c2)) === -1); @@ -392,8 +443,9 @@ export class Player extends Actor { return new Promise(resolve => { this.walkingQueue.process(); - if(this.updateFlags.mapRegionUpdateRequired) { - if(this.position.x >= 6400) { // Custom map drawing area is anywhere x >= 6400 on the map + if (this.updateFlags.mapRegionUpdateRequired) { + if (this.position.x >= 6400) { + // Custom map drawing area is anywhere x >= 6400 on the map if (this.metadata.customMap) { this.outgoingPackets.constructMapRegion(this.metadata.customMap); } else { @@ -409,7 +461,7 @@ export class Player extends Actor { } public async update(): Promise { - await Promise.all([ this.playerUpdateTask.execute(), this.npcUpdateTask.execute() ]); + await Promise.all([this.playerUpdateTask.execute(), this.npcUpdateTask.execute()]); } public async reset(): Promise { @@ -418,7 +470,7 @@ export class Player extends Actor { this.outgoingPackets.flushQueue(); - if(this.metadata.updateChunk) { + if (this.metadata.updateChunk) { const { newChunk, oldChunk } = this.metadata.updateChunk; oldChunk.removePlayer(this); newChunk.addPlayer(this); @@ -426,7 +478,7 @@ export class Player extends Actor { this.metadata.updateChunk = undefined; } - if(this.metadata.teleporting) { + if (this.metadata.teleporting) { this.metadata.teleporting = undefined; } @@ -440,9 +492,8 @@ export class Player extends Actor { public getQuestPoints(): number { let questPoints = 0; - if(this.quests && this.quests.length !== 0) { - this.quests.filter(quest => quest.complete) - .forEach(quest => questPoints += questMap[quest.questId]?.points || 0); + if (this.quests && this.quests.length !== 0) { + this.quests.filter(quest => quest.complete).forEach(quest => (questPoints += questMap[quest.questId]?.points || 0)); } return questPoints; @@ -454,7 +505,7 @@ export class Player extends Actor { */ public getQuest(questId: string): PlayerQuest { let playerQuest = this.quests.find(quest => quest.questId === questId); - if(!playerQuest) { + if (!playerQuest) { playerQuest = new PlayerQuest(questId); this.quests.push(playerQuest); } @@ -469,12 +520,12 @@ export class Player extends Actor { * @return boolean if the player has reached the required stage, if the quest does not exist it defaults to true */ public hasQuestRequirement(questId: string, minimumStage: QuestKey = 'complete'): boolean { - if(!questMap[questId]) { + if (!questMap[questId]) { logger.warn(`Quest data not found for ${questId}`); return true; } let playerQuest = this.quests.find(quest => quest.questId === questId); - if(!playerQuest) { + if (!playerQuest) { playerQuest = new PlayerQuest(questId); this.quests.push(playerQuest); } @@ -489,66 +540,67 @@ export class Player extends Actor { public setQuestProgress(questId: string, progress: QuestKey): void { const questData = findQuest(questId); - if(!questData) { + if (!questData) { logger.warn(`Quest data not found for ${questId}`); return; } let playerQuest = this.quests.find(quest => quest.questId === questId); - if(!playerQuest) { + if (!playerQuest) { playerQuest = new PlayerQuest(questId); this.quests.push(playerQuest); } - if(playerQuest.progress === 0 && !playerQuest.complete) { + if (playerQuest.progress === 0 && !playerQuest.complete) { playerQuest.progress = progress; this.modifyWidget(widgets.questTab, { childId: questData.questTabId, textColor: colors.yellow }); - } else if(!playerQuest.complete && progress === 'complete') { + } else if (!playerQuest.complete && progress === 'complete') { playerQuest.complete = true; playerQuest.progress = 'complete'; this.outgoingPackets.updateClientConfig(widgetScripts.questPoints, questData.points + this.getQuestPoints()); this.modifyWidget(widgets.questReward, { childId: 2, text: `You have completed ${questData.name}!` }); this.modifyWidget(widgets.questReward, { childId: 8, - text: `${questData.points} Quest Point${questData.points > 1 ? 's' : ''}` + text: `${questData.points} Quest Point${questData.points > 1 ? 's' : ''}`, }); - for(let i = 0; i < 5; i++) { - if(i >= questData.onComplete.questCompleteWidget.rewardText.length) { + for (let i = 0; i < 5; i++) { + if (i >= questData.onComplete.questCompleteWidget.rewardText.length) { this.modifyWidget(widgets.questReward, { childId: 9 + i, text: '' }); } else { this.modifyWidget(widgets.questReward, { childId: 9 + i, - text: questData.onComplete.questCompleteWidget.rewardText[i] + text: questData.onComplete.questCompleteWidget.rewardText[i], }); } } - if(questData.onComplete.questCompleteWidget.itemId) { + if (questData.onComplete.questCompleteWidget.itemId) { const cacheItemData = filestore.configStore.itemStore.getItem(questData.onComplete.questCompleteWidget.itemId); if (cacheItemData && cacheItemData.model2d.widgetModel) { this.outgoingPackets.updateWidgetModel1(widgets.questReward, 3, cacheItemData.model2d.widgetModel); } - - - } else if(questData.onComplete.questCompleteWidget.modelId) { + } else if (questData.onComplete.questCompleteWidget.modelId) { this.outgoingPackets.updateWidgetModel1(widgets.questReward, 3, questData.onComplete.questCompleteWidget.modelId); } - this.outgoingPackets.setWidgetModelRotationAndZoom(widgets.questReward, 3, + this.outgoingPackets.setWidgetModelRotationAndZoom( + widgets.questReward, + 3, questData.onComplete.questCompleteWidget.modelRotationX || 0, questData.onComplete.questCompleteWidget.modelRotationY || 0, - questData.onComplete.questCompleteWidget.modelZoom || 0); + questData.onComplete.questCompleteWidget.modelZoom || 0, + ); this.interfaceState.openWidget(widgets.questReward, { slot: 'screen', - multi: false + multi: false, }); this.modifyWidget(widgets.questTab, { childId: questData.questTabId, textColor: colors.green }); - if(questData.onComplete.giveRewards) { + if (questData.onComplete.giveRewards) { questData.onComplete.giveRewards(this); } } else { @@ -561,17 +613,17 @@ export class Player extends Actor { * @param widgetId The widget id of the widget to modify. * @param options The options with which to modify the widget. */ - public modifyWidget(widgetId: number, options: { childId?: number, text?: string, hidden?: boolean, textColor?: number }): void { + public modifyWidget(widgetId: number, options: { childId?: number; text?: string; hidden?: boolean; textColor?: number }): void { const { childId, text, hidden, textColor } = options; - if(childId !== undefined) { - if(text !== undefined) { + if (childId !== undefined) { + if (text !== undefined) { this.outgoingPackets.updateWidgetString(widgetId, childId, text); } - if(hidden !== undefined) { + if (hidden !== undefined) { this.outgoingPackets.toggleWidgetVisibility(widgetId, childId, hidden); } - if(textColor !== undefined) { + if (textColor !== undefined) { const { r, g, b } = hexToRgb(textColor); this.outgoingPackets.updateWidgetColor(widgetId, childId, rgbTo16Bit(r, g, b)); } @@ -593,7 +645,7 @@ export class Player extends Actor { */ public playSong(songId: number): void { const musicTrack = findMusicTrack(songId); - if(!musicTrack) { + if (!musicTrack) { logger.warn(`Music track not found for id ${songId}`); return; } @@ -601,7 +653,7 @@ export class Player extends Actor { this.modifyWidget(widgets.musicPlayerTab, { childId: 177, text: musicTrack.songName, - textColor: colors.green + textColor: colors.green, }); this.savedMetadata['currentSongIdPlaying'] = songId; this.outgoingPackets.playSong(songId); @@ -637,14 +689,14 @@ export class Player extends Actor { public async sendMessage(messages: string | string[], options?: SendMessageOptions): Promise; public async sendMessage(messages: string | string[], options?: boolean | SendMessageOptions): Promise { - if(!Array.isArray(messages)) { - messages = [ messages ]; + if (!Array.isArray(messages)) { + messages = [messages]; } let showDialogue = false; let showInConsole = false; - if(options) { - if(typeof options === 'boolean') { + if (options) { + if (typeof options === 'boolean') { showDialogue = true; } else { showDialogue = options.dialogue || false; @@ -652,19 +704,17 @@ export class Player extends Actor { } } - if(!showDialogue) { + if (!showDialogue) { messages.forEach(message => this.outgoingPackets.chatboxMessage(message)); } else { - for(let i = 0; i < messages.length; i++) { + for (let i = 0; i < messages.length; i++) { messages[i] = messages[i]?.trim() || ''; } - return await dialogue([ this ], [ - text => (messages as string[]).join(' ') - ]); + return await dialogue([this], [text => (messages as string[]).join(' ')]); } - if(showInConsole) { + if (showInConsole) { messages.forEach(message => this.outgoingPackets.consoleMessage(message)); } @@ -689,14 +739,13 @@ export class Player extends Actor { const oldChunk = activeWorld.chunkManager.getChunkForWorldPosition(originalPosition); const newChunk = activeWorld.chunkManager.getChunkForWorldPosition(newPosition); - if(!oldChunk.equals(newChunk)) { + if (!oldChunk.equals(newChunk)) { oldChunk.removePlayer(this); newChunk.addPlayer(this); this.metadata.updateChunk = { newChunk, oldChunk }; - if(updateRegion) { - this.actionPipeline.call('region_change', regionChangeActionFactory( - this, originalPosition, newPosition, true)); + if (updateRegion) { + this.actionPipeline.call('region_change', regionChangeActionFactory(this, originalPosition, newPosition, true)); } } } @@ -711,7 +760,7 @@ export class Player extends Actor { public removeFirstItem(item: number | Item): number { const slot = this.inventory.removeFirst(item); - if(slot === -1) { + if (slot === -1) { return -1; } @@ -720,8 +769,7 @@ export class Player extends Actor { } public hasCoins(amount: number): number { - return this.inventory.items - .findIndex(item => item !== null && item.itemId === itemIds.coins && item.amount >= amount); + return this.inventory.items.findIndex(item => item !== null && item.itemId === itemIds.coins && item.amount >= amount); } public removeItem(slot: number): void { @@ -731,7 +779,7 @@ export class Player extends Actor { public giveItem(item: number | Item | string): boolean { const addedItem = this.inventory.add(item); - if(addedItem === null) { + if (addedItem === null) { return false; } @@ -751,7 +799,7 @@ export class Player extends Actor { const oldWeight = this._carryWeight; this._carryWeight = Math.round(this.inventory.weight() + this.equipment.weight()); - if(oldWeight !== this._carryWeight || force) { + if (oldWeight !== this._carryWeight || force) { this.outgoingPackets.updateCarryWeight(this._carryWeight); } } @@ -793,7 +841,7 @@ export class Player extends Actor { // 151: {setting: 'autoRetaliateEnabled', value: false} }; - if(!settingsMappings[buttonId]) { + if (!settingsMappings[buttonId]) { return; } @@ -807,8 +855,8 @@ export class Player extends Actor { public updateBonuses(): void { this.clearBonuses(); - for(const item of this._equipment.items) { - if(item === null) { + for (const item of this._equipment.items) { + if (item === null) { continue; } @@ -817,7 +865,7 @@ export class Player extends Actor { } public sendLogMessage(message: string, isConsole: boolean): void { - if(isConsole) { + if (isConsole) { this.outgoingPackets.consoleMessage(message); } else { this.outgoingPackets.chatboxMessage(message); @@ -825,21 +873,21 @@ export class Player extends Actor { } public sendCommandList(commands: PlayerCommandActionHook[]): void { - if(!commands || commands.length === 0) { + if (!commands || commands.length === 0) { return; } - for(const command of commands) { + for (const command of commands) { let strCmd: string; - if(Array.isArray(command.commands)) { + if (Array.isArray(command.commands)) { strCmd = command.commands.join('|'); } else { strCmd = command.commands; } let strHelp: string = ''; - if(command.args) { - for(const arg of command.args) { - if(arg.defaultValue !== undefined) { + if (command.args) { + for (const arg of command.args) { + if (arg.defaultValue !== undefined) { strHelp = `${strHelp} \\<${arg.name} = ${arg.defaultValue}>`; } else { strHelp = `${strHelp} \\<${arg.name}>`; @@ -851,9 +899,9 @@ export class Player extends Actor { } public isItemEquipped(item: number | Item | string): boolean { - if(typeof item === 'string') { + if (typeof item === 'string') { item = findItem(item)?.gameId || 0; - if(!item) { + if (!item) { return false; } } @@ -864,7 +912,6 @@ export class Player extends Actor { return this.equipment.items[equipmentIndex(equipmentSlot)] || null; } - /** * Check if a player can equip an item * @param item either an ItemDetails instance or the string id of the item to be checked @@ -873,11 +920,11 @@ export class Player extends Actor { * * defaults to equipable=true if the item string id does not exist */ - public canEquipItem(item: ItemDetails | string): { equipable: boolean, missingRequirements?: string[] } { - if(typeof item === 'string') { + public canEquipItem(item: ItemDetails | string): { equipable: boolean; missingRequirements?: string[] } { + if (typeof item === 'string') { item = itemMap[item]; - if(!item) { - return { equipable: true } + if (!item) { + return { equipable: true }; } } const missingRequirements: string[] = []; @@ -890,7 +937,10 @@ export class Player extends Actor { .map(([skill, level]) => `You need to be at least level ${level} ${skill} to equip this item.`), ...Object.entries(requirements.quests || {}) .filter(([quest, stage]) => this.hasQuestRequirement(quest, stage)) - .map(([quest]) => `You must progress further in the ${quest.replace(/^([a-z]+:)/gm, '').replace(/_/g, ' ')} quest to equip this item.`) + .map( + ([quest]) => + `You must progress further in the ${quest.replace(/^([a-z]+:)/gm, '').replace(/_/g, ' ')} quest to equip this item.`, + ), ); return { equipable: missingRequirements.length === 0, missingRequirements: missingRequirements }; @@ -899,13 +949,13 @@ export class Player extends Actor { public equipItem(itemId: number, itemSlot: number, slot: EquipmentSlot | number): boolean { const itemToEquip = getItemFromContainer(itemId, itemSlot, this.inventory); - if(!itemToEquip) { + if (!itemToEquip) { // The specified item was not found in the specified slot. return false; } let slotIndex: number; - if(typeof slot === 'number') { + if (typeof slot === 'number') { slotIndex = slot; slot = getEquipmentSlot(slotIndex); } else { @@ -917,41 +967,41 @@ export class Player extends Actor { let shouldUnequipMainHand = false; const itemDetails = findItem(itemId); - if(!itemDetails || !itemDetails.equipmentData || !itemDetails.equipmentData.equipmentSlot) { + if (!itemDetails || !itemDetails.equipmentData || !itemDetails.equipmentData.equipmentSlot) { this.sendMessage(`Unable to equip item ${itemId}: Missing equipment data.`); return false; } const equippable = this.canEquipItem(itemDetails); if (!equippable.equipable) { - if(equippable.missingRequirements) { - equippable.missingRequirements.forEach(async (s) => this.sendMessage(s)); + if (equippable.missingRequirements) { + equippable.missingRequirements.forEach(async s => this.sendMessage(s)); } return false; } - if(itemDetails && itemDetails.equipmentData) { - if(itemDetails.equipmentData.equipmentType === 'two_handed') { + if (itemDetails && itemDetails.equipmentData) { + if (itemDetails.equipmentData.equipmentType === 'two_handed') { shouldUnequipOffHand = true; } const mainHandEquipped = this.getEquippedItem('main_hand'); - if(slot === 'off_hand' && mainHandEquipped) { + if (slot === 'off_hand' && mainHandEquipped) { const mainHandItemData = findItem(mainHandEquipped.itemId); - if(mainHandItemData && mainHandItemData.equipmentData && mainHandItemData.equipmentData.equipmentType === 'two_handed') { + if (mainHandItemData && mainHandItemData.equipmentData && mainHandItemData.equipmentData.equipmentType === 'two_handed') { shouldUnequipMainHand = true; } } } - if(itemToUnequip) { - if(shouldUnequipOffHand && !this.unequipItem('off_hand', false)) { + if (itemToUnequip) { + if (shouldUnequipOffHand && !this.unequipItem('off_hand', false)) { return false; } - if(shouldUnequipMainHand && !this.unequipItem('main_hand', false)) { + if (shouldUnequipMainHand && !this.unequipItem('main_hand', false)) { return false; } @@ -962,16 +1012,15 @@ export class Player extends Actor { this.equipment.set(slotIndex, itemToEquip); this.inventory.set(itemSlot, itemToUnequip); - } else { this.equipment.set(slotIndex, itemToEquip); this.inventory.remove(itemSlot); - if(shouldUnequipOffHand) { + if (shouldUnequipOffHand) { this.unequipItem('off_hand'); } - if(shouldUnequipMainHand) { + if (shouldUnequipMainHand) { this.unequipItem('main_hand'); } } @@ -988,7 +1037,7 @@ export class Player extends Actor { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipment, this.equipment); - if(this.interfaceState.widgetOpen('screen', widgets.equipmentStats.widgetId)) { + if (this.interfaceState.widgetOpen('screen', widgets.equipmentStats.widgetId)) { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipmentStats, this.equipment); this.syncBonuses(); } @@ -1010,19 +1059,23 @@ export class Player extends Actor { { id: 117, text: 'Range', value: this.bonuses.defensive.ranged }, { id: 119, text: 'Strength', value: this.bonuses.skill.strength }, { id: 120, text: 'Prayer', value: this.bonuses.skill.prayer }, - ].forEach(bonus => this.modifyWidget(widgets.equipmentStats.widgetId, { childId: bonus.id, - text: `${bonus.text}: ${(bonus.value || 0) > 0 ? `+${bonus.value}` : bonus.value}` })); + ].forEach(bonus => + this.modifyWidget(widgets.equipmentStats.widgetId, { + childId: bonus.id, + text: `${bonus.text}: ${(bonus.value || 0) > 0 ? `+${bonus.value}` : bonus.value}`, + }), + ); } public unequipItem(slot: EquipmentSlot | number, updateRequired: boolean = true): boolean { const inventorySlot = this.inventory.getFirstOpenSlot(); - if(inventorySlot === -1) { + if (inventorySlot === -1) { this.sendMessage(`You don't have enough free space to do that.`); return false; } let slotIndex: number; - if(typeof slot === 'number') { + if (typeof slot === 'number') { slotIndex = slot; slot = getEquipmentSlot(slotIndex); } else { @@ -1031,7 +1084,7 @@ export class Player extends Actor { const itemInSlot = this.equipment.items[slotIndex]; - if(!itemInSlot) { + if (!itemInSlot) { return true; } @@ -1039,7 +1092,7 @@ export class Player extends Actor { this.equipment.remove(slotIndex); this.inventory.set(inventorySlot, itemInSlot); - if(updateRequired) { + if (updateRequired) { this.equipmentChanged(); } return true; @@ -1050,15 +1103,15 @@ export class Player extends Actor { * @param npc The NPC to copy the appearance of, or null to reset. */ public transformInto(npc: NpcDetails | string | number | null): void { - if(!npc) { + if (!npc) { delete this.savedMetadata.npcTransformation; this.updateFlags.appearanceUpdateRequired = true; return; } - if(typeof npc !== 'number') { - if(typeof npc === 'string') { - if(npc.indexOf(':') !== -1) { + if (typeof npc !== 'number') { + if (typeof npc === 'string') { + if (npc.indexOf(':') !== -1) { npc = npcIdMap[npc]; } else { npc = parseInt(npc, 10); @@ -1068,7 +1121,7 @@ export class Player extends Actor { } } - if(!npc) { + if (!npc) { logger.error(`NPC not found.`); return; } @@ -1090,9 +1143,12 @@ export class Player extends Actor { if (originalNpc.varbitId !== -1) { morphIndex = getVarbitMorphIndex(originalNpc.varbitId, this.metadata.configs); } else if (originalNpc.settingId !== -1) { - morphIndex = this.metadata.configs && this.metadata.configs[originalNpc.settingId] ? this.metadata.configs[originalNpc.settingId] : 0; + morphIndex = + this.metadata.configs && this.metadata.configs[originalNpc.settingId] ? this.metadata.configs[originalNpc.settingId] : 0; } else { - logger.warn(`Tried to fetch a child NPC index, but but no varbitId or settingId were found in the NPC details. NPC: ${originalNpc.id}, childrenIDs: ${originalNpc.childrenIds}`); + logger.warn( + `Tried to fetch a child NPC index, but but no varbitId or settingId were found in the NPC details. NPC: ${originalNpc.id}, childrenIDs: ${originalNpc.childrenIds}`, + ); return null; } @@ -1104,15 +1160,14 @@ export class Player extends Actor { } private inventoryUpdated(event: ContainerUpdateEvent): void { - if(event.type === 'CLEAR_ALL') { + if (event.type === 'CLEAR_ALL') { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); - } else if(event.type === 'ADD') { + } else if (event.type === 'ADD') { if (event.slot !== undefined && event.item !== undefined) { this.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, event.slot, event.item); } else { logger.error(`Inventory update event was missing slot or item.`, event); } - } this.updateCarryWeight(); } @@ -1134,34 +1189,31 @@ export class Player extends Actor { const chunkUpdateItems: ChunkUpdateItem[] = []; - const chunkModifications = instance - .getInstancedChunk(chunk.position.x, chunk.position.y, chunk.position.level) || null; - const personalChunkModifications = this.personalInstance?.getInstancedChunk(chunk.position.x, - chunk.position.y, chunk.position.level) || null; + const chunkModifications = instance.getInstancedChunk(chunk.position.x, chunk.position.y, chunk.position.level) || null; + const personalChunkModifications = + this.personalInstance?.getInstancedChunk(chunk.position.x, chunk.position.y, chunk.position.level) || null; this.findChunkUpdates(chunkModifications?.mods, chunkUpdateItems); this.findChunkUpdates(personalChunkModifications?.mods, chunkUpdateItems); - if(chunkUpdateItems.length !== 0) { + if (chunkUpdateItems.length !== 0) { this.outgoingPackets.updateChunk(chunk, chunkUpdateItems); } }); } private findChunkUpdates(chunkMods: Map, chunkUpdateItems: ChunkUpdateItem[]): void { - if(!chunkMods) { + if (!chunkMods) { return; } Array.from(chunkMods.values()).forEach(worldMods => { - worldMods.hiddenObjects?.forEach(object => - chunkUpdateItems.push({ object, type: 'REMOVE' })); + worldMods.hiddenObjects?.forEach(object => chunkUpdateItems.push({ object, type: 'REMOVE' })); - worldMods.spawnedObjects?.forEach(object => - chunkUpdateItems.push({ object, type: 'ADD' })); + worldMods.spawnedObjects?.forEach(object => chunkUpdateItems.push({ object, type: 'ADD' })); worldMods.worldItems?.forEach(worldItem => { - if(!worldItem.owner || worldItem.owner.equals(this)) { + if (!worldItem.owner || worldItem.owner.equals(this)) { chunkUpdateItems.push({ worldItem, type: 'ADD' }); } }); @@ -1174,7 +1226,7 @@ export class Player extends Actor { private updateQuestTab(): void { this.outgoingPackets.updateClientConfig(widgetScripts.questPoints, this.getQuestPoints()); - if(!questMap) { + if (!questMap) { return; } Object.keys(questMap).forEach(questKey => { @@ -1202,13 +1254,13 @@ export class Player extends Actor { * Updates the player's music tab progress. */ private updateMusicTab(): void { - if(!this.savedMetadata['currentSongIdPlaying']) { - this.savedMetadata['currentSongIdPlaying'] = - findSongIdByRegionId(activeWorld.chunkManager.getRegionIdForWorldPosition( - this.position)); + if (!this.savedMetadata['currentSongIdPlaying']) { + this.savedMetadata['currentSongIdPlaying'] = findSongIdByRegionId( + activeWorld.chunkManager.getRegionIdForWorldPosition(this.position), + ); } - if(this.settings.musicPlayerMode === MusicPlayerMode.MANUAL) { + if (this.settings.musicPlayerMode === MusicPlayerMode.MANUAL) { this.playSong(this.savedMetadata['currentSongIdPlaying']); } @@ -1216,7 +1268,7 @@ export class Player extends Actor { const musicData = musicRegions[key]; let color = colors.red; - if(this.musicTracks.includes(musicData.songId)) { + if (this.musicTracks.includes(musicData.songId)) { color = colors.green; } @@ -1227,7 +1279,7 @@ export class Player extends Actor { private addBonuses(item: Item): void { const itemData = findItem(item.itemId); - if(!itemData || !itemData.equipmentData) { + if (!itemData || !itemData.equipmentData) { return; } @@ -1235,19 +1287,20 @@ export class Player extends Actor { const defensiveBonuses = itemData.equipmentData.defensiveBonuses; const skillBonuses = itemData.equipmentData.skillBonuses; - if(offensiveBonuses) { - [ 'speed', 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => - this.bonuses.offensive[bonus] += (!offensiveBonuses[bonus] ? 0 : offensiveBonuses[bonus])); + if (offensiveBonuses) { + ['speed', 'stab', 'slash', 'crush', 'magic', 'ranged'].forEach( + bonus => (this.bonuses.offensive[bonus] += !offensiveBonuses[bonus] ? 0 : offensiveBonuses[bonus]), + ); } - if(defensiveBonuses) { - [ 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => - this.bonuses.defensive[bonus] += (!defensiveBonuses[bonus] ? 0 : defensiveBonuses[bonus])); + if (defensiveBonuses) { + ['stab', 'slash', 'crush', 'magic', 'ranged'].forEach( + bonus => (this.bonuses.defensive[bonus] += !defensiveBonuses[bonus] ? 0 : defensiveBonuses[bonus]), + ); } - if(skillBonuses) { - [ 'strength', 'prayer' ].forEach(bonus => this.bonuses.skill[bonus] += - (!skillBonuses[bonus] ? 0 : skillBonuses[bonus])); + if (skillBonuses) { + ['strength', 'prayer'].forEach(bonus => (this.bonuses.skill[bonus] += !skillBonuses[bonus] ? 0 : skillBonuses[bonus])); } } @@ -1256,23 +1309,23 @@ export class Player extends Actor { const firstTimePlayer = playerSave === null; this.firstTimePlayer = firstTimePlayer; - if(!firstTimePlayer) { - if(playerSave.savedMetadata) { + if (!firstTimePlayer) { + if (playerSave.savedMetadata) { this.savedMetadata = playerSave.savedMetadata; } // Existing player logging in this.position = new Position(playerSave.position.x, playerSave.position.y, playerSave.position.level); - if(playerSave.inventory && playerSave.inventory.length !== 0) { + if (playerSave.inventory && playerSave.inventory.length !== 0) { this.inventory.setAll(playerSave.inventory); } - if(playerSave.bank && playerSave.bank.length !== 0) { + if (playerSave.bank && playerSave.bank.length !== 0) { this.bank.setAll(playerSave.bank); } - if(playerSave.equipment && playerSave.equipment.length !== 0) { + if (playerSave.equipment && playerSave.equipment.length !== 0) { this.equipment.setAll(playerSave.equipment); } - if(playerSave.skills && playerSave.skills.length !== 0) { + if (playerSave.skills && playerSave.skills.length !== 0) { this.skills.values = playerSave.skills; } this._appearance = playerSave.appearance; @@ -1280,25 +1333,25 @@ export class Player extends Actor { this._rights = playerSave.rights || Rights.USER; const lastLogin = playerSave.lastLogin?.date; - if(!lastLogin) { + if (!lastLogin) { this._loginDate = new Date(); } else { this._loginDate = new Date(lastLogin); } - if(playerSave.questList) { + if (playerSave.questList) { this.quests = playerSave.questList; } - if(playerSave.musicTracks) { + if (playerSave.musicTracks) { this.musicTracks = playerSave.musicTracks; } - if(playerSave.achievements) { + if (playerSave.achievements) { this.achievements = playerSave.achievements; } - if(playerSave.friendsList) { + if (playerSave.friendsList) { this.friendsList = playerSave.friendsList; } - if(playerSave.ignoreList) { + if (playerSave.ignoreList) { this.ignoreList = playerSave.ignoreList; } @@ -1310,11 +1363,11 @@ export class Player extends Actor { this._rights = Rights.USER; this.savedMetadata = { tutorialProgress: 0, - tutorialComplete: false + tutorialComplete: false, }; } - if(!this._settings) { + if (!this._settings) { this._settings = defaultSettings(); } } @@ -1322,7 +1375,7 @@ export class Player extends Actor { public set position(position: Position) { super.position = position; - if(this.quadtreeKey !== null) { + if (this.quadtreeKey !== null) { activeWorld.playerTree.remove(this.quadtreeKey); } @@ -1374,7 +1427,6 @@ export class Player extends Actor { return this._equipment; } - public get carryWeight(): number { return this._carryWeight; } @@ -1392,15 +1444,14 @@ export class Player extends Actor { } public set instance(value: WorldInstance | null) { - if(this.instance?.instanceId) { + if (this.instance?.instanceId) { this.instance.removePlayer(this); } - if(value) { + if (value) { value.addPlayer(this); } this._instance = value; } - } diff --git a/src/engine/world/actor/player/private-messaging.ts b/src/engine/world/actor/player/private-messaging.ts index 8db2fdc83..25861576a 100644 --- a/src/engine/world/actor/player/private-messaging.ts +++ b/src/engine/world/actor/player/private-messaging.ts @@ -1,14 +1,13 @@ -import type { Player } from '@engine/world/actor/player/player'; import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; export enum PrivateChatMode { PUBLIC = 0, FRIENDS = 1, - OFF = 2 + OFF = 2, } export class PrivateMessaging { - public static friendAdded(player: Player, friendName: string): void { friendName = friendName.toLowerCase(); const friend = activeWorld?.findPlayer(friendName); @@ -18,9 +17,9 @@ export class PrivateMessaging { friendName = friendName.toLowerCase(); const playerPrivateChatMode = player.settings.privateChatMode; const playerUsername = player.username.toLowerCase(); - if(playerPrivateChatMode !== PrivateChatMode.PUBLIC) { + if (playerPrivateChatMode !== PrivateChatMode.PUBLIC) { const friend = activeWorld?.findPlayer(friendName); - if(friend && friend.friendsList.indexOf(playerUsername) !== -1) { + if (friend && friend.friendsList.indexOf(playerUsername) !== -1) { // Friend being removed is currently online - update their friends list if they have this player added friend.outgoingPackets.updateFriendStatus(player.username, 0); } @@ -33,20 +32,22 @@ export class PrivateMessaging { */ public static updateFriendsList(player: Player): void { const friends = player.friendsList; - if(friends && friends.length !== 0) { + if (friends && friends.length !== 0) { const onlineFriends = activeWorld.playerList.filter(p => p && friends.indexOf(p.username.toLowerCase()) !== -1); friends.forEach(friendName => { const friend = onlineFriends.find(p => p.username.toLowerCase() === friendName); - if(!friend || friend.settings.privateChatMode === PrivateChatMode.OFF) { + if (!friend || friend.settings.privateChatMode === PrivateChatMode.OFF) { player.outgoingPackets.updateFriendStatus(friendName, 0); } else { - if(friend.settings.privateChatMode === PrivateChatMode.PUBLIC) { + if (friend.settings.privateChatMode === PrivateChatMode.PUBLIC) { player.outgoingPackets.updateFriendStatus(friendName, 1); } else { const otherPlayerFriendsList = friend.friendsList; - player.outgoingPackets.updateFriendStatus(friendName, - otherPlayerFriendsList.indexOf(player.username.toLowerCase()) !== -1 ? 1 : 0); + player.outgoingPackets.updateFriendStatus( + friendName, + otherPlayerFriendsList.indexOf(player.username.toLowerCase()) !== -1 ? 1 : 0, + ); } } }); @@ -63,14 +64,14 @@ export class PrivateMessaging { const playerPrivateChatMode: PrivateChatMode = player.settings.privateChatMode; const playerFriendsList = player.friendsList || []; - if(playerPrivateChatMode !== PrivateChatMode.OFF || updating) { + if (playerPrivateChatMode !== PrivateChatMode.OFF || updating) { const otherPlayers = activeWorld.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); - if(otherPlayers && otherPlayers.length !== 0) { + if (otherPlayers && otherPlayers.length !== 0) { otherPlayers.forEach(otherPlayer => { let worldId = playerPrivateChatMode === PrivateChatMode.OFF ? 0 : 1; - if(playerPrivateChatMode === PrivateChatMode.FRIENDS) { - if(playerFriendsList.findIndex(playerName => playerName === otherPlayer.username.toLowerCase()) === -1) { + if (playerPrivateChatMode === PrivateChatMode.FRIENDS) { + if (playerFriendsList.findIndex(playerName => playerName === otherPlayer.username.toLowerCase()) === -1) { worldId = 0; } } @@ -85,5 +86,4 @@ export class PrivateMessaging { PrivateMessaging.playerPrivateChatModeChanged(player, false); PrivateMessaging.updateFriendsList(player); } - } diff --git a/src/engine/world/actor/player/quest.ts b/src/engine/world/actor/player/quest.ts index a582515ff..1a1df91c6 100644 --- a/src/engine/world/actor/player/quest.ts +++ b/src/engine/world/actor/player/quest.ts @@ -1,8 +1,6 @@ import type { QuestCompletion, QuestJournalHandler } from '@engine/config/quest-config'; - export class Quest { - public id: string; public questTabId: number; public name: string; @@ -25,5 +23,4 @@ export class Quest { this.journalHandler = options.journalHandler; this.onComplete = options.onComplete; } - } diff --git a/src/engine/world/actor/player/sync/actor-sync.ts b/src/engine/world/actor/player/sync/actor-sync.ts index 3b6e05770..b5e450902 100644 --- a/src/engine/world/actor/player/sync/actor-sync.ts +++ b/src/engine/world/actor/player/sync/actor-sync.ts @@ -1,59 +1,64 @@ import type { ByteBuffer } from '@runejs/common'; import type { Packet } from '@engine/net/packet'; +import { activeWorld } from '@engine/world'; import type { Npc } from '@engine/world/actor/npc'; import type { Position } from '@engine/world/position'; +import type { QuadtreeKey } from '@engine/world/world'; import type { Actor } from '../../actor'; -import type { Player } from '../player'; -import { activeWorld } from '@engine/world'; import { isNpc, isPlayer } from '../../util'; -import type { QuadtreeKey } from '@engine/world/world'; +import type { Player } from '../player'; /** * Handles the registration of nearby NPCs or Players for the specified player. */ -export function registerNewActors(packet: Packet, player: Player, trackedActors: Actor[], nearbyActors: QuadtreeKey[], - registerActor: (actor: Actor) => void): void { - if(trackedActors.length >= 255) { +export function registerNewActors( + packet: Packet, + player: Player, + trackedActors: Actor[], + nearbyActors: QuadtreeKey[], + registerActor: (actor: Actor) => void, +): void { + if (trackedActors.length >= 255) { return; } // We only want to send about 20 new actors at a time, to help save some memory and computing time // Any remaining players or npcs will be automatically picked up by subsequent updates let newActors: QuadtreeKey[] = nearbyActors.filter(m1 => !trackedActors.includes(m1.actor)); - if(newActors.length > 50) { + if (newActors.length > 50) { // We also sort the list of players or npcs here by how close they are to the current player if there are more than 80, so we can render the nearest first newActors = newActors .sort((a, b) => player.position.distanceBetween(a.actor.position) - player.position.distanceBetween(b.actor.position)) .slice(0, 50); } - for(const newActor of newActors) { + for (const newActor of newActors) { const nearbyActor = newActor.actor; - if(isPlayer(nearbyActor)) { - if(player.equals(nearbyActor)) { + if (isPlayer(nearbyActor)) { + if (player.equals(nearbyActor)) { // Other player is actually this player! continue; } - if(!activeWorld.playerOnline(nearbyActor)) { + if (!activeWorld.playerOnline(nearbyActor)) { // Other player is no longer in the game world continue; } - } else if(isNpc(nearbyActor)) { - if(!activeWorld.npcExists(nearbyActor)) { + } else if (isNpc(nearbyActor)) { + if (!activeWorld.npcExists(nearbyActor)) { // Npc is no longer in the game world continue; } } - if(trackedActors.findIndex(m => m.equals(nearbyActor)) !== -1) { + if (trackedActors.findIndex(m => m.equals(nearbyActor)) !== -1) { // Npc or other player is already tracked by this player continue; } - if(!nearbyActor.position.withinViewDistance(player.position)) { + if (!nearbyActor.position.withinViewDistance(player.position)) { // Player or npc is still too far away to be worth rendering // Also - values greater than 15 and less than -15 are too large, or too small, to be sent via 5 bits (max length of 32) continue; @@ -61,7 +66,7 @@ export function registerNewActors(packet: Packet, player: Player, trackedActors: // Only 255 players or npcs are able to be rendered at a time // To help performance, we limit it to 200 here - if(trackedActors.length >= 255) { + if (trackedActors.length >= 255) { return; } @@ -72,33 +77,41 @@ export function registerNewActors(packet: Packet, player: Player, trackedActors: /** * Handles synchronization of nearby NPCs or Players for the specified player. */ -export function syncTrackedActors(packet: Packet, playerPosition: Position, appendUpdateMaskData: (actor: Actor) => void, - trackedActors: Actor[], nearbyActors: QuadtreeKey[]): Actor[] { +export function syncTrackedActors( + packet: Packet, + playerPosition: Position, + appendUpdateMaskData: (actor: Actor) => void, + trackedActors: Actor[], + nearbyActors: QuadtreeKey[], +): Actor[] { packet.putBits(8, trackedActors.length); // Tracked actor count - if(trackedActors.length === 0) { + if (trackedActors.length === 0) { return []; } const existingTrackedActors: Actor[] = []; - for(let i = 0; i < trackedActors.length; i++) { + for (let i = 0; i < trackedActors.length; i++) { const trackedActor: Actor = trackedActors[i]; let exists = true; - if(isPlayer(trackedActor)) { - if(!activeWorld.playerOnline(trackedActor)) { + if (isPlayer(trackedActor)) { + if (!activeWorld.playerOnline(trackedActor)) { exists = false; } } else { - if(!activeWorld.npcExists(trackedActor as Npc)) { + if (!activeWorld.npcExists(trackedActor as Npc)) { exists = false; } } - if(exists && nearbyActors.findIndex(m => m.actor.equals(trackedActor)) !== -1 - && trackedActor.position.withinViewDistance(playerPosition) - && !trackedActor.metadata.teleporting) { + if ( + exists && + nearbyActors.findIndex(m => m.actor.equals(trackedActor)) !== -1 && + trackedActor.position.withinViewDistance(playerPosition) && + !trackedActor.metadata.teleporting + ) { appendMovement(trackedActor, packet); appendUpdateMaskData(trackedActor); existingTrackedActors.push(trackedActor); @@ -116,11 +129,11 @@ export function syncTrackedActors(packet: Packet, playerPosition: Position, appe * Appends movement data of a player or NPC to the specified synchronization packet. */ export function appendMovement(actor: Actor, packet: ByteBuffer): void { - if(actor.walkDirection !== -1) { + if (actor.walkDirection !== -1) { // Actor is walking/running packet.putBits(1, 1); // Update required - if(actor.runDirection === -1) { + if (actor.runDirection === -1) { // Actor is walking packet.putBits(2, 1); // Actor walking packet.putBits(3, actor.walkDirection); @@ -134,7 +147,7 @@ export function appendMovement(actor: Actor, packet: ByteBuffer): void { packet.putBits(1, actor.updateFlags.updateBlockRequired ? 1 : 0); // Whether or not an update flag block follows } else { // Did not move - if(actor.updateFlags.updateBlockRequired) { + if (actor.updateFlags.updateBlockRequired) { packet.putBits(1, 1); // Update required packet.putBits(2, 0); // Signify the player did not move } else { @@ -144,7 +157,5 @@ export function appendMovement(actor: Actor, packet: ByteBuffer): void { } export abstract class SyncTask { - public abstract execute(): Promise; - } diff --git a/src/engine/world/actor/player/sync/npc-sync-task.ts b/src/engine/world/actor/player/sync/npc-sync-task.ts index 0ee676335..e2c9de868 100644 --- a/src/engine/world/actor/player/sync/npc-sync-task.ts +++ b/src/engine/world/actor/player/sync/npc-sync-task.ts @@ -1,17 +1,16 @@ import { ByteBuffer } from '@runejs/common'; import { Packet, PacketType } from '@engine/net/packet'; -import type { Npc } from '@engine/world/actor/npc'; -import { registerNewActors, SyncTask, syncTrackedActors } from './actor-sync'; -import type { Player } from '../player'; import { activeWorld } from '@engine/world'; +import type { Npc } from '@engine/world/actor/npc'; import { isPlayer } from '@engine/world/actor/util'; +import type { Player } from '../player'; +import { SyncTask, registerNewActors, syncTrackedActors } from './actor-sync'; /** * Handles the chonky npc synchronization packet for a specific player. */ export class NpcSyncTask extends SyncTask { - private readonly player: Player; public constructor(player: Player) { @@ -26,18 +25,25 @@ export class NpcSyncTask extends SyncTask { const updateMaskData = new ByteBuffer(5000); - const nearbyNpcs = activeWorld.npcTree.colliding({ - x: this.player.position.x - 15, - y: this.player.position.y - 15, - width: 32, - height: 32 - }).filter(collision => { - const npc = collision?.actor as Npc || null; - return npc && npc.initialized && npc.instanceId === this.player.instance.instanceId; - }); - - this.player.trackedNpcs = syncTrackedActors(npcUpdatePacket, this.player.position, - actor => this.appendUpdateMaskData(actor as Npc, updateMaskData), this.player.trackedNpcs, nearbyNpcs) as Npc[]; + const nearbyNpcs = activeWorld.npcTree + .colliding({ + x: this.player.position.x - 15, + y: this.player.position.y - 15, + width: 32, + height: 32, + }) + .filter(collision => { + const npc = (collision?.actor as Npc) || null; + return npc && npc.initialized && npc.instanceId === this.player.instance.instanceId; + }); + + this.player.trackedNpcs = syncTrackedActors( + npcUpdatePacket, + this.player.position, + actor => this.appendUpdateMaskData(actor as Npc, updateMaskData), + this.player.trackedNpcs, + nearbyNpcs, + ) as Npc[]; registerNewActors(npcUpdatePacket, this.player, this.player.trackedNpcs, nearbyNpcs, actor => { const newNpc = actor as Npc; @@ -59,7 +65,7 @@ export class NpcSyncTask extends SyncTask { this.appendUpdateMaskData(newNpc, updateMaskData); }); - if(updateMaskData.writerIndex !== 0) { + if (updateMaskData.writerIndex !== 0) { npcUpdatePacket.putBits(15, 32767); npcUpdatePacket.closeBitBuffer(); @@ -87,28 +93,28 @@ export class NpcSyncTask extends SyncTask { */ private appendUpdateMaskData(npc: Npc, updateMaskData: ByteBuffer): void { const updateFlags = npc.updateFlags; - if(!updateFlags.updateBlockRequired) { + if (!updateFlags.updateBlockRequired) { return; } let mask = 0; - if(updateFlags.damage !== null) { + if (updateFlags.damage !== null) { mask |= 0x1; } - if(updateFlags.appearanceUpdateRequired) { + if (updateFlags.appearanceUpdateRequired) { mask |= 0x80; } if (updateFlags.faceActor !== null) { mask |= 0x4; } - if(updateFlags.chatMessages.length !== 0) { + if (updateFlags.chatMessages.length !== 0) { mask |= 0x40; } if (updateFlags.facePosition !== null) { mask |= 0x8; } - if(updateFlags.animation) { + if (updateFlags.animation) { mask |= 0x10; } @@ -125,9 +131,9 @@ export class NpcSyncTask extends SyncTask { } updateMaskData.put(npc.worldIndex, 'SHORT'); alreadyPutWorldIndex = true; - } + }; - if(updateFlags.damage !== null) { + if (updateFlags.damage !== null) { const damage = updateFlags.damage; updateMaskData.put(damage.damageDealt); updateMaskData.put(damage.damageType.valueOf()); @@ -146,7 +152,7 @@ export class NpcSyncTask extends SyncTask { } else { let worldIndex = actor.worldIndex; - if(isPlayer(actor)) { + if (isPlayer(actor)) { // Client checks if index is less than 32768. // If it is, it looks for an NPC. // If it isn't, it looks for a player (subtracting 32768 to find the index). @@ -159,10 +165,10 @@ export class NpcSyncTask extends SyncTask { putWorldIndex(); } - if(updateFlags.chatMessages.length !== 0) { + if (updateFlags.chatMessages.length !== 0) { const message = updateFlags.chatMessages[0]; - if(message.message) { + if (message.message) { updateMaskData.putString(message.message); } else { updateMaskData.putString('Undefined Message'); @@ -171,22 +177,22 @@ export class NpcSyncTask extends SyncTask { putWorldIndex(); } - if(updateFlags.appearanceUpdateRequired) { + if (updateFlags.appearanceUpdateRequired) { updateMaskData.put(npc.id, 'SHORT'); putWorldIndex(); } - if(updateFlags.facePosition) { + if (updateFlags.facePosition) { const position = updateFlags.facePosition; updateMaskData.put(position.x * 2 + 1, 'SHORT'); updateMaskData.put(position.y * 2 + 1, 'SHORT', 'LITTLE_ENDIAN'); putWorldIndex(); } - if(updateFlags.animation) { + if (updateFlags.animation) { const animation = updateFlags.animation; - if(animation === null || animation.id === -1) { + if (animation === null || animation.id === -1) { // Reset animation updateMaskData.put(65535, 'SHORT'); updateMaskData.put(0); @@ -205,5 +211,4 @@ export class NpcSyncTask extends SyncTask { putWorldIndex(); } } - } diff --git a/src/engine/world/actor/player/sync/player-sync-task.ts b/src/engine/world/actor/player/sync/player-sync-task.ts index eea3d47b4..dd7dac34e 100644 --- a/src/engine/world/actor/player/sync/player-sync-task.ts +++ b/src/engine/world/actor/player/sync/player-sync-task.ts @@ -1,20 +1,19 @@ import { ByteBuffer } from '@runejs/common'; -import type { UpdateFlags } from '@engine/world/actor/update-flags'; -import { Packet, PacketType } from '@engine/net/packet'; -import { stringToLong } from '@engine/util/strings'; import { findItem, findNpc } from '@engine/config/config-handler'; import type { EquipmentSlot, EquipmentType, ItemDetails } from '@engine/config/item-config'; -import { appendMovement, registerNewActors, SyncTask, syncTrackedActors } from './actor-sync'; -import type { Player } from '../player'; +import { Packet, PacketType } from '@engine/net/packet'; +import { stringToLong } from '@engine/util/strings'; import { activeWorld } from '@engine/world'; +import type { UpdateFlags } from '@engine/world/actor/update-flags'; import { isPlayer } from '@engine/world/actor/util'; +import type { Player } from '../player'; +import { SyncTask, appendMovement, registerNewActors, syncTrackedActors } from './actor-sync'; /** * Handles the chonky player synchronization packet. */ export class PlayerSyncTask extends SyncTask { - private readonly player: Player; public constructor(player: Player) { @@ -30,7 +29,7 @@ export class PlayerSyncTask extends SyncTask { const updateMaskData = new ByteBuffer(5000); - if(updateFlags.mapRegionUpdateRequired || this.player.metadata.teleporting) { + if (updateFlags.mapRegionUpdateRequired || this.player.metadata.teleporting) { playerUpdatePacket.putBits(1, 1); // Update Required playerUpdatePacket.putBits(2, 3); // Map Region changed (movement type - 0=nomove, 1=walk, 2=run, 3=mapchange playerUpdatePacket.putBits(1, this.player.metadata.teleporting ? 1 : 0); // Whether or not the client should discard the current walking queue (1 if teleporting, 0 if not) @@ -44,24 +43,31 @@ export class PlayerSyncTask extends SyncTask { this.appendUpdateMaskData(this.player, updateMaskData, false); - let nearbyPlayers = activeWorld.playerTree.colliding({ - x: this.player.position.x - 15, - y: this.player.position.y - 15, - width: 32, - height: 32 - }).filter(collision => collision?.actor && collision.actor.instance === this.player.instance); + let nearbyPlayers = activeWorld.playerTree + .colliding({ + x: this.player.position.x - 15, + y: this.player.position.y - 15, + width: 32, + height: 32, + }) + .filter(collision => collision?.actor && collision.actor.instance === this.player.instance); - if(nearbyPlayers.length > 200) { + if (nearbyPlayers.length > 200) { nearbyPlayers = activeWorld.playerTree.colliding({ x: this.player.position.x - 7, y: this.player.position.y - 7, width: 16, - height: 16 + height: 16, }); } - this.player.trackedPlayers = syncTrackedActors(playerUpdatePacket, this.player.position, - actor => this.appendUpdateMaskData(actor as Player, updateMaskData), this.player.trackedPlayers, nearbyPlayers) as Player[]; + this.player.trackedPlayers = syncTrackedActors( + playerUpdatePacket, + this.player.position, + actor => this.appendUpdateMaskData(actor as Player, updateMaskData), + this.player.trackedPlayers, + nearbyPlayers, + ) as Player[]; registerNewActors(playerUpdatePacket, this.player, this.player.trackedPlayers, nearbyPlayers, actor => { const newPlayer = actor as Player; @@ -83,7 +89,7 @@ export class PlayerSyncTask extends SyncTask { this.appendUpdateMaskData(newPlayer, updateMaskData, true); }); - if(updateMaskData.writerIndex !== 0) { + if (updateMaskData.writerIndex !== 0) { playerUpdatePacket.putBits(11, 2047); playerUpdatePacket.closeBitBuffer(); @@ -101,35 +107,35 @@ export class PlayerSyncTask extends SyncTask { private appendUpdateMaskData(player: Player, updateMaskData: ByteBuffer, forceUpdate?: boolean): void { const updateFlags = player.updateFlags; - if(!updateFlags.updateBlockRequired && !forceUpdate) { + if (!updateFlags.updateBlockRequired && !forceUpdate) { return; } let mask: number = 0; - if(updateFlags.damage !== null) { + if (updateFlags.damage !== null) { mask |= 0x100; } - if(updateFlags.appearanceUpdateRequired || forceUpdate) { + if (updateFlags.appearanceUpdateRequired || forceUpdate) { mask |= 0x20; } - if(updateFlags.chatMessages.length !== 0) { + if (updateFlags.chatMessages.length !== 0) { mask |= 0x8; } if (updateFlags.faceActor !== null) { mask |= 0x4; } - if(updateFlags.facePosition) { + if (updateFlags.facePosition) { mask |= 0x10; } - if(updateFlags.graphics) { + if (updateFlags.graphics) { mask |= 0x200; } - if(updateFlags.animation !== undefined && updateFlags.animation !== null) { + if (updateFlags.animation !== undefined && updateFlags.animation !== null) { mask |= 0x1; } - if(mask >= 0x100) { + if (mask >= 0x100) { mask |= 0x2; updateMaskData.put(mask & 0xff); updateMaskData.put(mask >> 8); @@ -137,7 +143,7 @@ export class PlayerSyncTask extends SyncTask { updateMaskData.put(mask); } - if(updateFlags.damage !== null) { + if (updateFlags.damage !== null) { const damage = updateFlags.damage; updateMaskData.put(damage.damageDealt); updateMaskData.put(damage.damageType.valueOf()); @@ -145,16 +151,16 @@ export class PlayerSyncTask extends SyncTask { updateMaskData.put(damage.maxHitpoints); } - if(updateFlags.facePosition) { + if (updateFlags.facePosition) { const position = updateFlags.facePosition; updateMaskData.put(position.x * 2 + 1, 'SHORT'); updateMaskData.put(position.y * 2 + 1, 'SHORT', 'LITTLE_ENDIAN'); } - if(updateFlags.animation !== undefined && updateFlags.animation !== null) { + if (updateFlags.animation !== undefined && updateFlags.animation !== null) { const animation = updateFlags.animation; - if(animation === null || animation.id === -1) { + if (animation === null || animation.id === -1) { // Reset animation updateMaskData.put(-1, 'SHORT', 'LITTLE_ENDIAN'); updateMaskData.put(0, 'BYTE'); @@ -173,7 +179,7 @@ export class PlayerSyncTask extends SyncTask { const actor = updateFlags.faceActor; let worldIndex = actor.worldIndex; - if(isPlayer(actor)) { + if (isPlayer(actor)) { // Client checks if index is less than 32768. // If it is, it looks for an NPC. // If it isn't, it looks for a player (subtracting 32768 to find the index). @@ -184,36 +190,36 @@ export class PlayerSyncTask extends SyncTask { } } - if(updateFlags.chatMessages.length !== 0) { + if (updateFlags.chatMessages.length !== 0) { const message = updateFlags.chatMessages[0]; if (!message.data) { throw new Error('Chat message data is undefined'); } - updateMaskData.put(((message.color || 0 & 0xFF) << 8) + (message.effects || 0 & 0xFF), 'SHORT'); + updateMaskData.put(((message.color || 0 & 0xff) << 8) + (message.effects || 0 & 0xff), 'SHORT'); updateMaskData.put(player.rights.valueOf(), 'BYTE'); updateMaskData.put(message.data.length, 'BYTE'); - for(let i = 0; i < message.data.length; i++) { + for (let i = 0; i < message.data.length; i++) { updateMaskData.put(message.data.readInt8(i), 'BYTE'); } } - if(updateFlags.appearanceUpdateRequired || forceUpdate) { + if (updateFlags.appearanceUpdateRequired || forceUpdate) { const equipment = player.equipment; const appearanceData = new ByteBuffer(500); appearanceData.put(player.appearance.gender); // Gender appearanceData.put(-1); // Skull Icon appearanceData.put(-1); // Prayer Icon - if(player.savedMetadata.npcTransformation) { + if (player.savedMetadata.npcTransformation) { appearanceData.put(65535, 'SHORT'); appearanceData.put(player.savedMetadata.npcTransformation, 'SHORT'); } else { - for(let i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { const item = equipment.items[i]; - if(item) { + if (item) { appearanceData.put(0x200 + item.itemId, 'SHORT'); } else { appearanceData.put(0); @@ -222,7 +228,7 @@ export class PlayerSyncTask extends SyncTask { const torsoItem = player.getEquippedItem('torso'); let torsoItemData: ItemDetails | null = null; - if(torsoItem) { + if (torsoItem) { torsoItemData = findItem(torsoItem.itemId); appearanceData.put(0x200 + torsoItem.itemId, 'SHORT'); } else { @@ -230,14 +236,18 @@ export class PlayerSyncTask extends SyncTask { } const offHandItem = player.getEquippedItem('off_hand'); - if(offHandItem) { + if (offHandItem) { appearanceData.put(0x200 + offHandItem.itemId, 'SHORT'); } else { appearanceData.put(0); } - if(torsoItemData && torsoItemData.equipmentData && torsoItemData.equipmentData.equipmentType && - torsoItemData.equipmentData.equipmentType === 'full_top') { + if ( + torsoItemData && + torsoItemData.equipmentData && + torsoItemData.equipmentData.equipmentType && + torsoItemData.equipmentData.equipmentType === 'full_top' + ) { appearanceData.put(0); } else { appearanceData.put(0x100 + player.appearance.arms, 'SHORT'); @@ -249,19 +259,19 @@ export class PlayerSyncTask extends SyncTask { let helmetType: EquipmentType | null = null; let fullHelmet = false; - if(headItem) { + if (headItem) { const headItemData = findItem(headItem.itemId); - if(headItemData && headItemData.equipmentData && headItemData.equipmentData.equipmentType) { + if (headItemData && headItemData.equipmentData && headItemData.equipmentData.equipmentType) { helmetType = headItemData.equipmentData.equipmentType; - if(helmetType === 'helmet') { + if (helmetType === 'helmet') { fullHelmet = true; } } } - if(!headItem || helmetType === 'hat') { + if (!headItem || helmetType === 'hat') { appearanceData.put(0x100 + player.appearance.head, 'SHORT'); } else { appearanceData.put(0); @@ -270,7 +280,7 @@ export class PlayerSyncTask extends SyncTask { this.appendBasicAppearanceItem(appearanceData, player, player.appearance.hands, 'hands'); this.appendBasicAppearanceItem(appearanceData, player, player.appearance.feet, 'feet'); - if(player.appearance.gender === 1 || fullHelmet) { + if (player.appearance.gender === 1 || fullHelmet) { appearanceData.put(0); } else { appearanceData.put(0x100 + player.appearance.facialHair, 'SHORT'); @@ -295,7 +305,7 @@ export class PlayerSyncTask extends SyncTask { 0x338, // run ]; - if(player.savedMetadata.npcTransformation) { + if (player.savedMetadata.npcTransformation) { const npc = findNpc(player.savedMetadata.npcTransformation); animations = [ npc.animations?.stand || 0x328, // stand @@ -320,20 +330,19 @@ export class PlayerSyncTask extends SyncTask { updateMaskData.putBytes(appearanceData.flipWriter()); } - if(updateFlags.graphics) { + if (updateFlags.graphics) { const delay = updateFlags.graphics.delay || 0; updateMaskData.put(updateFlags.graphics.id, 'SHORT', 'LITTLE_ENDIAN'); - updateMaskData.put(updateFlags.graphics.height << 16 | delay & 0xffff, 'INT'); + updateMaskData.put((updateFlags.graphics.height << 16) | (delay & 0xffff), 'INT'); } } private appendBasicAppearanceItem(buffer: ByteBuffer, player: Player, appearanceInfo: number, equipmentSlot: EquipmentSlot): void { const item = player.getEquippedItem(equipmentSlot); - if(item) { + if (item) { buffer.put(0x200 + item.itemId, 'SHORT'); } else { buffer.put(0x100 + appearanceInfo, 'SHORT'); } } - } diff --git a/src/engine/world/actor/skills.ts b/src/engine/world/actor/skills.ts index 211a1dc3f..24fce3fc8 100644 --- a/src/engine/world/actor/skills.ts +++ b/src/engine/world/actor/skills.ts @@ -1,10 +1,10 @@ +import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; import { startsWithVowel } from '@engine/util/strings'; +import type { Player } from '@engine/world/actor/player/player'; +import { gfxIds } from '@engine/world/config/gfx-ids'; import { serverConfig } from '@server/game/game-server'; import type { Actor } from './actor'; -import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; import { isPlayer } from './util'; -import type { Player } from '@engine/world/actor/player/player'; -import { gfxIds } from '@engine/world/config/gfx-ids'; export enum Skill { ATTACK, @@ -28,12 +28,32 @@ export enum Skill { SLAYER, FARMING, RUNECRAFTING, - CONSTRUCTION = 22 + CONSTRUCTION = 22, } -export type SkillName = 'attack' | 'defence' | 'strength' | 'hitpoints' | 'ranged' | 'prayer' | 'magic' | 'cooking' | - 'woodcutting' | 'fletching' | 'fishing' | 'firemaking' | 'crafting' | 'smithing' | 'mining' | 'herblore' | - 'agility' | 'thieving' | 'slayer' | 'farming' | 'runecrafting' | 'construction'; +export type SkillName = + | 'attack' + | 'defence' + | 'strength' + | 'hitpoints' + | 'ranged' + | 'prayer' + | 'magic' + | 'cooking' + | 'woodcutting' + | 'fletching' + | 'fishing' + | 'firemaking' + | 'crafting' + | 'smithing' + | 'mining' + | 'herblore' + | 'agility' + | 'thieving' + | 'slayer' + | 'farming' + | 'runecrafting' + | 'construction'; export interface SkillDetail { readonly name: string; @@ -63,7 +83,7 @@ export const skillDetails: SkillDetail[] = [ { name: 'Farming', advancementWidgetId: 162 }, { name: 'Runecrafting', advancementWidgetId: 172 }, null as unknown as SkillDetail, // (Jameskmonger) this is a placeholder - { name: 'Construction' } + { name: 'Construction' }, ]; export interface SkillValue { @@ -73,9 +93,10 @@ export interface SkillValue { } export class SkillShortcut { - - public constructor(private skills: Skills, private skillName: SkillName) { - } + public constructor( + private skills: Skills, + private skillName: SkillName, + ) {} public addExp(exp: number): void { this.skills.addExp(this.skillName, exp); @@ -100,7 +121,6 @@ export class SkillShortcut { public get levelForExp(): number { return this.skills.getLevelForExp(this.exp); } - } type SkillShortcutMap = { @@ -133,16 +153,13 @@ class SkillShortcuts implements SkillShortcutMap { } export class Skills extends SkillShortcuts { - private static EXPERIENCE_LOOKUP_TABLE: number[] = [ - 0,83,174,276,388,512,650,801,969,1154,1358,1584,1833,2107,2411,2746,3115,3523, - 3973,4470,5018,5624,6291,7028,7842,8740,9730,10824,12031,13363,14833,16456,18247, - 20224,22406,24815,27473,30408,33648,37224,41171,45529,50339,55649,61512,67983,75127, - 83014,91721,101333,111945,123660,136594,150872,166636,184040,203254,224466,247886, - 273742,302288,333804,368599,407015,449428,496254,547953,605032,668051,737627,814445, - 899257,992895,1096278,1210421,1336443,1475581,1629200,1798808,1986068,2192818,2421087, - 2673114,2951373,3258594,3597792,3972294,4385776,4842295,5346332,5902831,6517253,7195629, - 7944614,8771558,9684577,10692629,11805606,13034431 + 0, 83, 174, 276, 388, 512, 650, 801, 969, 1154, 1358, 1584, 1833, 2107, 2411, 2746, 3115, 3523, 3973, 4470, 5018, 5624, 6291, 7028, + 7842, 8740, 9730, 10824, 12031, 13363, 14833, 16456, 18247, 20224, 22406, 24815, 27473, 30408, 33648, 37224, 41171, 45529, 50339, + 55649, 61512, 67983, 75127, 83014, 91721, 101333, 111945, 123660, 136594, 150872, 166636, 184040, 203254, 224466, 247886, 273742, + 302288, 333804, 368599, 407015, 449428, 496254, 547953, 605032, 668051, 737627, 814445, 899257, 992895, 1096278, 1210421, 1336443, + 1475581, 1629200, 1798808, 1986068, 2192818, 2421087, 2673114, 2951373, 3258594, 3597792, 3972294, 4385776, 4842295, 5346332, + 5902831, 6517253, 7195629, 7944614, 8771558, 9684577, 10692629, 11805606, 13034431, ]; private static MAXIMUM_EXPERIENCE: number = 200000000; @@ -152,16 +169,17 @@ export class Skills extends SkillShortcuts { private _values: SkillValue[]; - public constructor(private actor: Actor, values?: SkillValue[]) { + public constructor( + private actor: Actor, + values?: SkillValue[], + ) { super(); Object.keys(Skill) .map(skillName => skillName.toLowerCase()) - .forEach(skillName => - this[skillName] = new SkillShortcut(this, skillName as SkillName) - ); + .forEach(skillName => (this[skillName] = new SkillShortcut(this, skillName as SkillName))); - if(values) { + if (values) { this._values = values; } else { this._values = this.defaultValues(); @@ -177,8 +195,7 @@ export class Skills extends SkillShortcuts { } public getTotalLevel(): number { - return this._values.map(skillValue => skillValue.level) - .reduce((accumulator, currentValue) => accumulator + currentValue); + return this._values.map(skillValue => skillValue.level).reduce((accumulator, currentValue) => accumulator + currentValue); } public getCombatLevel(): number { @@ -189,10 +206,9 @@ export class Skills extends SkillShortcuts { return combatLevel + Math.max(melee, Math.max(ranger, mage)); } - public getLevel(skill: number | SkillName, ignoreLevelModifications: boolean = false): number { const s = this.get(skill); - return (s.modifiedLevel !== undefined && !ignoreLevelModifications ? s.modifiedLevel : s.level); + return s.modifiedLevel !== undefined && !ignoreLevelModifications ? s.modifiedLevel : s.level; } public hasLevel(skill: number | SkillName, level: number, ignoreLevelModifications: boolean = false): boolean { @@ -200,7 +216,7 @@ export class Skills extends SkillShortcuts { } public getLevelForExp(exp: number, index: number | undefined = undefined): number { - const start = Skills.confine((index || Skills.MAXIMUM_INDEX), Skills.MINIMUM_LEVEL, Skills.MAXIMUM_INDEX); + const start = Skills.confine(index || Skills.MAXIMUM_INDEX, Skills.MINIMUM_LEVEL, Skills.MAXIMUM_INDEX); for (let level = start; level >= 1; level--) { const requirement = Skills.EXPERIENCE_LOOKUP_TABLE[level]; if (exp >= requirement) { @@ -218,7 +234,7 @@ export class Skills extends SkillShortcuts { public addExp(skill: number | SkillName, exp: number): void { const currentExp = this.get(skill).exp; const currentLevel = this.getLevelForExp(currentExp); - let finalExp = currentExp + (exp * serverConfig.expRate); + let finalExp = currentExp + exp * serverConfig.expRate; if (finalExp > Skills.MAXIMUM_EXPERIENCE) { finalExp = Skills.MAXIMUM_EXPERIENCE; } @@ -227,16 +243,16 @@ export class Skills extends SkillShortcuts { this.setExp(skill, finalExp); - if(isPlayer(this.actor)) { + if (isPlayer(this.actor)) { this.actor.outgoingPackets.updateSkill(this.getSkillId(skill), finalLevel, finalExp); } - if(currentLevel !== finalLevel) { + if (currentLevel !== finalLevel) { this.setLevel(skill, finalLevel); - if(isPlayer(this.actor)) { + if (isPlayer(this.actor)) { const achievementDetails = skillDetails[this.getSkillId(skill)]; - if(!achievementDetails) { + if (!achievementDetails) { return; } @@ -250,20 +266,30 @@ export class Skills extends SkillShortcuts { * dialogue being shown after other events get processed on the * tick that the xp drop occurred. */ - this.actor.enqueueBaseTask(new QueueableTask([], this.actor, () => { - (this.actor as Player).sendMessage(`Congratulations, you just advanced a ` + `${ achievementDetails.name.toLowerCase() } level.`); - this.showLevelUpDialogue(skill, finalLevel); - return { - callbackResult: false, - shouldContinueLooping: false, - } - } , null, null)) + this.actor.enqueueBaseTask( + new QueueableTask( + [], + this.actor, + () => { + (this.actor as Player).sendMessage( + `Congratulations, you just advanced a ` + `${achievementDetails.name.toLowerCase()} level.`, + ); + this.showLevelUpDialogue(skill, finalLevel); + return { + callbackResult: false, + shouldContinueLooping: false, + }; + }, + null, + null, + ), + ); } } } public showLevelUpDialogue(skill: number | SkillName, level: number): void { - if(!isPlayer(this.actor)) { + if (!isPlayer(this.actor)) { return; } @@ -271,7 +297,7 @@ export class Skills extends SkillShortcuts { const achievementDetails = skillDetails[this.getSkillId(skill)]; const widgetId = achievementDetails.advancementWidgetId; - if(!widgetId) { + if (!widgetId) { return; } @@ -279,17 +305,17 @@ export class Skills extends SkillShortcuts { player.modifyWidget(widgetId, { childId: 0, - text: `Congratulations, you just advanced ${ startsWithVowel(skillName) ? 'an' : 'a' } ` + - `${ skillName } level.` + text: + `Congratulations, you just advanced ${startsWithVowel(skillName) ? 'an' : 'a'} ` + `${skillName} level.`, }); player.modifyWidget(widgetId, { childId: 1, - text: `Your ${ skillName } level is now ${ level }.` + text: `Your ${skillName} level is now ${level}.`, }); player.interfaceState.openWidget(widgetId, { slot: 'chatbox', - multi: true + multi: true, }); player.playGraphics({ id: gfxIds.levelUpFireworks, delay: 0, height: 125 }); @@ -297,7 +323,7 @@ export class Skills extends SkillShortcuts { } public getSkillId(skill: number | SkillName): number { - if(typeof skill === 'number') { + if (typeof skill === 'number') { return skill; } else { const skillName = skill.toString().toUpperCase(); @@ -306,7 +332,7 @@ export class Skills extends SkillShortcuts { } public get(skill: number | SkillName): SkillValue { - if(typeof skill === 'number') { + if (typeof skill === 'number') { return this._values[skill]; } else { const skillName = skill.toString().toUpperCase(); diff --git a/src/engine/world/actor/update-flags.ts b/src/engine/world/actor/update-flags.ts index 720cfc15e..36fe3751c 100644 --- a/src/engine/world/actor/update-flags.ts +++ b/src/engine/world/actor/update-flags.ts @@ -31,7 +31,7 @@ export interface Animation { export enum DamageType { NO_DAMAGE = 0, DAMAGE = 1, - POISON = 2 + POISON = 2, } /** @@ -48,7 +48,6 @@ export interface Damage { * Various actor updating flags. */ export class UpdateFlags { - private _mapRegionUpdateRequired: boolean; private _appearanceUpdateRequired: boolean; private _chatMessages: ChatMessage[]; @@ -72,7 +71,7 @@ export class UpdateFlags { this._animation = null; this._damage = null; - if(this._chatMessages.length !== 0) { + if (this._chatMessages.length !== 0) { this._chatMessages.shift(); } } @@ -81,12 +80,13 @@ export class UpdateFlags { this.damage = { damageDealt: amount, damageType: type, - remainingHitpoints, maxHitpoints + remainingHitpoints, + maxHitpoints, }; } public addChatMessage(chatMessage: ChatMessage): void { - if(this._chatMessages.length > 4) { + if (this._chatMessages.length > 4) { return; } diff --git a/src/engine/world/actor/util.ts b/src/engine/world/actor/util.ts index 2a64fa538..5211f3b8f 100644 --- a/src/engine/world/actor/util.ts +++ b/src/engine/world/actor/util.ts @@ -1,5 +1,5 @@ -import type { Npc } from './npc'; import type { Actor } from './actor'; +import type { Npc } from './npc'; import type { Player } from './player/player'; export const isPlayer = (actor: Actor): actor is Player => actor.type === 'player'; diff --git a/src/engine/world/actor/walking-queue.ts b/src/engine/world/actor/walking-queue.ts index a5a6d4c2b..787d90413 100644 --- a/src/engine/world/actor/walking-queue.ts +++ b/src/engine/world/actor/walking-queue.ts @@ -1,16 +1,14 @@ -import type { Actor } from './actor'; -import { Position } from '../position'; -import { Subject } from 'rxjs'; -import { activeWorld } from '@engine/world'; import { regionChangeActionFactory } from '@engine/action/pipe/region-change.action'; +import { activeWorld } from '@engine/world'; import { isNpc, isPlayer } from '@engine/world/actor/util'; - +import { Subject } from 'rxjs'; +import { Position } from '../position'; +import type { Actor } from './actor'; /** * Controls an actor's movement. */ export class WalkingQueue { - public readonly movementQueued = new Subject(); public readonly movementEvent = new Subject(); public readonly movementQueued$ = this.movementQueued.asObservable(); @@ -33,7 +31,7 @@ export class WalkingQueue { } public getLastPosition(): Position { - if(this.queue.length === 0) { + if (this.queue.length === 0) { return this.actor.position; } else { return this.queue[this.queue.length - 1]; @@ -50,12 +48,12 @@ export class WalkingQueue { const stepsBetween = Math.max(Math.abs(diffX), Math.abs(diffY)); - for(let i = 0; i < stepsBetween; i++) { - if(diffX !== 0) { + for (let i = 0; i < stepsBetween; i++) { + if (diffX !== 0) { diffX += diffX < 0 ? 1 : -1; } - if(diffY !== 0) { + if (diffY !== 0) { diffY += diffY < 0 ? 1 : -1; } @@ -64,11 +62,11 @@ export class WalkingQueue { const newPosition = new Position(lastX, lastY, this.actor.position.level); - if(this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { + if (this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { lastPosition = newPosition; newPosition.metadata = { ...newPosition.metadata, - ...positionMetadata + ...positionMetadata, }; this.queue.push(newPosition); this.movementQueued.next(newPosition); @@ -78,13 +76,13 @@ export class WalkingQueue { } } - if(lastX !== x || lastY !== y && this.valid) { + if (lastX !== x || (lastY !== y && this.valid)) { const newPosition = new Position(x, y, this.actor.position.level); - if(this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { + if (this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { newPosition.metadata = { ...newPosition.metadata, - ...positionMetadata + ...positionMetadata, }; this.queue.push(newPosition); this.movementQueued.next(newPosition); @@ -98,7 +96,7 @@ export class WalkingQueue { const position = this.actor.position; const newPosition = new Position(position.x + xDiff, position.y + yDiff, position.level); - if(this.actor.pathfinding.canMoveTo(position, newPosition)) { + if (this.actor.pathfinding.canMoveTo(position, newPosition)) { this.clear(); this.valid = true; this.add(newPosition.x, newPosition.y, { ignoreWidgets: true }); @@ -114,26 +112,26 @@ export class WalkingQueue { } public calculateDirection(diffX: number, diffY: number): number { - if(diffX < 0) { - if(diffY < 0) { + if (diffX < 0) { + if (diffY < 0) { return 5; - } else if(diffY > 0) { + } else if (diffY > 0) { return 0; } else { return 3; } - } else if(diffX > 0) { - if(diffY < 0) { + } else if (diffX > 0) { + if (diffY < 0) { return 7; - } else if(diffY > 0) { + } else if (diffY > 0) { return 2; } else { return 4; } } else { - if(diffY < 0) { + if (diffY < 0) { return 6; - } else if(diffY > 0) { + } else if (diffY > 0) { return 1; } else { return -1; @@ -142,7 +140,7 @@ export class WalkingQueue { } public process(): void { - if(this.actor.busy || this.queue.length === 0 || !this.valid) { + if (this.actor.busy || this.queue.length === 0 || !this.valid) { this.resetDirections(); return; } @@ -153,13 +151,13 @@ export class WalkingQueue { return; } - if(this.actor.metadata.faceActorClearedByWalking === undefined || this.actor.metadata.faceActorClearedByWalking) { + if (this.actor.metadata.faceActorClearedByWalking === undefined || this.actor.metadata.faceActorClearedByWalking) { this.actor.clearFaceActor(); } const originalPosition = this.actor.position; - if(this.actor.pathfinding.canMoveTo(originalPosition, walkPosition)) { + if (this.actor.pathfinding.canMoveTo(originalPosition, walkPosition)) { const oldChunk = activeWorld.chunkManager.getChunkForWorldPosition(originalPosition); const lastMapRegionUpdatePosition = this.actor.lastMapRegionUpdatePosition; @@ -167,7 +165,7 @@ export class WalkingQueue { const walkDiffY = walkPosition.y - originalPosition.y; const walkDir = this.calculateDirection(walkDiffX, walkDiffY); - if(walkDir === -1) { + if (walkDir === -1) { this.resetDirections(); return; } @@ -178,20 +176,20 @@ export class WalkingQueue { let runDir = -1; // @TODO npc running - if(isPlayer(this.actor)) { - if(this.actor.settings.runEnabled && this.queue.length !== 0) { + if (isPlayer(this.actor)) { + if (this.actor.settings.runEnabled && this.queue.length !== 0) { const runPosition = this.queue.shift(); if (!runPosition) { return; } - if(this.actor.pathfinding.canMoveTo(walkPosition, runPosition)) { + if (this.actor.pathfinding.canMoveTo(walkPosition, runPosition)) { const runDiffX = runPosition.x - walkPosition.x; const runDiffY = runPosition.y - walkPosition.y; runDir = this.calculateDirection(runDiffX, runDiffY); - if(runDir != -1) { + if (runDir != -1) { this.actor.lastMovementPosition = this.actor.position; this.actor.position = runPosition; } @@ -205,7 +203,7 @@ export class WalkingQueue { this.actor.walkDirection = walkDir; this.actor.runDirection = runDir; - if(runDir !== -1) { + if (runDir !== -1) { this.actor.faceDirection = runDir; } else { this.actor.faceDirection = walkDir; @@ -215,22 +213,24 @@ export class WalkingQueue { this.movementEvent.next(this.actor.position); - if(isPlayer(this.actor)) { - const mapDiffX = this.actor.position.x - (lastMapRegionUpdatePosition.chunkX * 8); - const mapDiffY = this.actor.position.y - (lastMapRegionUpdatePosition.chunkY * 8); - if(mapDiffX < 16 || mapDiffX > 87 || mapDiffY < 16 || mapDiffY > 87) { + if (isPlayer(this.actor)) { + const mapDiffX = this.actor.position.x - lastMapRegionUpdatePosition.chunkX * 8; + const mapDiffY = this.actor.position.y - lastMapRegionUpdatePosition.chunkY * 8; + if (mapDiffX < 16 || mapDiffX > 87 || mapDiffY < 16 || mapDiffY > 87) { this.actor.updateFlags.mapRegionUpdateRequired = true; this.actor.lastMapRegionUpdatePosition = this.actor.position; } } - if(!oldChunk.equals(newChunk)) { - if(isPlayer(this.actor)) { + if (!oldChunk.equals(newChunk)) { + if (isPlayer(this.actor)) { this.actor.metadata.updateChunk = { newChunk, oldChunk }; - this.actor.actionPipeline.call('region_change', regionChangeActionFactory( - this.actor, originalPosition, this.actor.position)); - } else if(isNpc(this.actor)) { + this.actor.actionPipeline.call( + 'region_change', + regionChangeActionFactory(this.actor, originalPosition, this.actor.position), + ); + } else if (isNpc(this.actor)) { oldChunk.removeNpc(this.actor); newChunk.addNpc(this.actor); } diff --git a/src/engine/world/config/animation-ids.ts b/src/engine/world/config/animation-ids.ts index de718ee94..e6f044130 100644 --- a/src/engine/world/config/animation-ids.ts +++ b/src/engine/world/config/animation-ids.ts @@ -28,10 +28,10 @@ export const animationIds = { kick: 423, stab: 412, slash: 451, - armBlock: 424 + armBlock: 424, }, fadeOut: 3541, fadeIn: 2115, transparent: 15, - teleport: 714 + teleport: 714, }; diff --git a/src/engine/world/config/examine-data.ts b/src/engine/world/config/examine-data.ts index a0695ed8a..73e4d5140 100644 --- a/src/engine/world/config/examine-data.ts +++ b/src/engine/world/config/examine-data.ts @@ -19,17 +19,17 @@ export class ExamineCache { this.objects = new Map(); } - public getItem (id: number): string | null { + public getItem(id: number): string | null { const examine = this.items.get(id); return examine ? examine.examine : null; } - public getNpc (id: number): string | null { + public getNpc(id: number): string | null { const examine = this.npcs.get(id); return examine ? examine.examine : null; } - public getObject (id: number): string | null { + public getObject(id: number): string | null { const examine = this.objects.get(id); return examine ? examine.examine : null; } @@ -40,14 +40,14 @@ function parseData(fileName: string): Map { try { const examineItems = load(readFileSync(fileName, 'utf8'), { schema: JSON_SCHEMA }) as Examine[]; - if(!examineItems || examineItems.length === 0) { + if (!examineItems || examineItems.length === 0) { throw new Error('Unable to read examine data.'); } for (const item of examineItems) { examineMap.set(item.id, item); } - } catch(error) { + } catch (error) { logger.error('Error parsing examine data: ' + error); } diff --git a/src/engine/world/config/gfx-ids.ts b/src/engine/world/config/gfx-ids.ts index 0318271a3..dce0c8f2d 100644 --- a/src/engine/world/config/gfx-ids.ts +++ b/src/engine/world/config/gfx-ids.ts @@ -5,5 +5,5 @@ export const gfxIds = { homeTeleportCircleGlow: 803, homeTeleport: 804, levelUpFireworks: 199, - teleport: 111 + teleport: 111, }; diff --git a/src/engine/world/config/harvest-tool.ts b/src/engine/world/config/harvest-tool.ts index 7c321d84f..f5efea10c 100644 --- a/src/engine/world/config/harvest-tool.ts +++ b/src/engine/world/config/harvest-tool.ts @@ -7,7 +7,6 @@ export interface HarvestTool { animation: number; } - export enum Pickaxe { BRONZE, IRON, @@ -24,20 +23,18 @@ export enum Axe { MITHRIL, ADAMANT, RUNE, - DRAGON + DRAGON, } - const Pickaxes: HarvestTool[] = [ { itemId: 1265, level: 1, animation: 625 }, { itemId: 1267, level: 1, animation: 626 }, { itemId: 1269, level: 6, animation: 627 }, { itemId: 1273, level: 21, animation: 629 }, { itemId: 1271, level: 31, animation: 628 }, - { itemId: 1275, level: 41, animation: 624 } + { itemId: 1275, level: 41, animation: 624 }, ]; - const Axes: HarvestTool[] = [ { itemId: 1351, level: 1, animation: 879 }, { itemId: 1349, level: 1, animation: 877 }, @@ -45,7 +42,7 @@ const Axes: HarvestTool[] = [ { itemId: 1355, level: 21, animation: 871 }, { itemId: 1357, level: 31, animation: 869 }, { itemId: 1359, level: 41, animation: 867 }, - { itemId: 6739, level: 61, animation: 2846 } + { itemId: 6739, level: 61, animation: 2846 }, ]; /** @@ -83,7 +80,6 @@ export function getPickaxe(pickaxe: Pickaxe): HarvestTool { return Pickaxes[pickaxe]; } - export function getAxe(axe: Axe): HarvestTool { return Axes[axe]; } diff --git a/src/engine/world/config/harvestable-object.ts b/src/engine/world/config/harvestable-object.ts index 7e7eb936f..ed5faa633 100644 --- a/src/engine/world/config/harvestable-object.ts +++ b/src/engine/world/config/harvestable-object.ts @@ -17,98 +17,105 @@ export interface IHarvestable { break: number; } - // Object maps work with key is mineable object, value is empty ore -const CLAY_OBJECTS: Map = new Map([ - ...objectIds.default.clay.map((tree) => [tree.default, tree.empty]), -] as [number, number][]); +const CLAY_OBJECTS: Map = new Map([...objectIds.default.clay.map(tree => [tree.default, tree.empty])] as [ + number, + number, +][]); const COPPER_OBJECTS: Map = new Map([ - ...objectIds.default.copper.map((tree) => [tree.default, tree.empty]), + ...objectIds.default.copper.map(tree => [tree.default, tree.empty]), ] as [number, number][]); -const TIN_OBJECTS: Map = new Map([ - ...objectIds.default.tin.map((tree) => [tree.default, tree.empty]), -] as [number, number][]); +const TIN_OBJECTS: Map = new Map([...objectIds.default.tin.map(tree => [tree.default, tree.empty])] as [ + number, + number, +][]); -const IRON_OBJECTS: Map = new Map([ - ...objectIds.default.iron.map((tree) => [tree.default, tree.empty]), -] as [number, number][]); +const IRON_OBJECTS: Map = new Map([...objectIds.default.iron.map(tree => [tree.default, tree.empty])] as [ + number, + number, +][]); -const COAL_OBJECTS: Map = new Map([ - ...objectIds.default.coal.map((tree) => [tree.default, tree.empty]), -] as [number, number][]); +const COAL_OBJECTS: Map = new Map([...objectIds.default.coal.map(tree => [tree.default, tree.empty])] as [ + number, + number, +][]); const SILVER_OBJECTS: Map = new Map([ - ...objectIds.default.silver.map((tree) => [tree.default, tree.empty]), + ...objectIds.default.silver.map(tree => [tree.default, tree.empty]), ] as [number, number][]); -const GOLD_OBJECTS: Map = new Map([ - ...objectIds.default.gold.map((tree) => [tree.default, tree.empty]), -] as [number, number][]); +const GOLD_OBJECTS: Map = new Map([...objectIds.default.gold.map(tree => [tree.default, tree.empty])] as [ + number, + number, +][]); const MITHRIL_OBJECTS: Map = new Map([ - ...objectIds.default.mithril.map((tree) => [tree.default, tree.empty]), + ...objectIds.default.mithril.map(tree => [tree.default, tree.empty]), ] as [number, number][]); - const ADAMANT_OBJECTS: Map = new Map([ - ...objectIds.default.adamant.map((tree) => [tree.default, tree.empty]), + ...objectIds.default.adamant.map(tree => [tree.default, tree.empty]), ] as [number, number][]); const RUNITE_OBJECTS: Map = new Map([ - ...objectIds.default.runite.map((tree) => [tree.default, tree.empty]), + ...objectIds.default.runite.map(tree => [tree.default, tree.empty]), ] as [number, number][]); const NORMAL_OBJECTS: Map = new Map([ - ...objectIds.tree.normal.map((tree) => [tree.default, tree.stump]), - ...objectIds.tree.dead.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - -const ACHEY_OBJECTS: Map = new Map([ - ...objectIds.tree.archey.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - -const OAK_OBJECTS: Map = new Map([ - ...objectIds.tree.oak.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - - -const WILLOW_OBJECTS: Map = new Map([ - ...objectIds.tree.willow.map((tree) => [tree.default, tree.stump]), + ...objectIds.tree.normal.map(tree => [tree.default, tree.stump]), + ...objectIds.tree.dead.map(tree => [tree.default, tree.stump]), ] as [number, number][]); - -const TEAK_OBJECTS: Map = new Map([ - ...objectIds.tree.teak.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - -const DRAMEN_OBJECTS: Map = new Map([ - ...objectIds.tree.dramen.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - - -const MAPLE_OBJECTS: Map = new Map([ - ...objectIds.tree.maple.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - - -const HOLLOW_OBJECTS: Map = new Map([ - ...objectIds.tree.hollow.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); +const ACHEY_OBJECTS: Map = new Map([...objectIds.tree.archey.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const OAK_OBJECTS: Map = new Map([...objectIds.tree.oak.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const WILLOW_OBJECTS: Map = new Map([...objectIds.tree.willow.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const TEAK_OBJECTS: Map = new Map([...objectIds.tree.teak.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const DRAMEN_OBJECTS: Map = new Map([...objectIds.tree.dramen.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const MAPLE_OBJECTS: Map = new Map([...objectIds.tree.maple.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); + +const HOLLOW_OBJECTS: Map = new Map([...objectIds.tree.hollow.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); const MAHOGANY_OBJECTS: Map = new Map([ - ...objectIds.tree.mahogany.map((tree) => [tree.default, tree.stump]), + ...objectIds.tree.mahogany.map(tree => [tree.default, tree.stump]), ] as [number, number][]); +const YEW_OBJECTS: Map = new Map([...objectIds.tree.yew.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); -const YEW_OBJECTS: Map = new Map([ - ...objectIds.tree.yew.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); - -const MAGIC_OBJECTS: Map = new Map([ - ...objectIds.tree.magic.map((tree) => [tree.default, tree.stump]), -] as [number, number][]); +const MAGIC_OBJECTS: Map = new Map([...objectIds.tree.magic.map(tree => [tree.default, tree.stump])] as [ + number, + number, +][]); export enum Ore { CLAY, @@ -122,10 +129,9 @@ export enum Ore { ADAMANT, RUNITE, RUNE_ESS, - GEM + GEM, } - export enum Tree { NORMAL, ACHEY, @@ -140,7 +146,6 @@ export enum Tree { DRAMEN, } - export function selectWeightedItem(items: WeightedItem[]): string { const totalWeight = items.reduce((sum, item) => sum + item.weight, 0); let random = randomBetween(1, totalWeight); @@ -164,7 +169,7 @@ const Ores: IHarvestable[] = [ respawnLow: 5, respawnHigh: 10, baseChance: 70, - break: 100 + break: 100, }, { objects: COPPER_OBJECTS, @@ -174,7 +179,7 @@ const Ores: IHarvestable[] = [ respawnLow: 10, respawnHigh: 20, baseChance: 70, - break: 100 + break: 100, }, { objects: TIN_OBJECTS, @@ -184,7 +189,7 @@ const Ores: IHarvestable[] = [ respawnLow: 10, respawnHigh: 20, baseChance: 70, - break: 100 + break: 100, }, { objects: IRON_OBJECTS, @@ -194,7 +199,7 @@ const Ores: IHarvestable[] = [ respawnLow: 9, respawnHigh: 9, baseChance: 0.0085, - break: 100 + break: 100, }, { objects: COAL_OBJECTS, @@ -204,7 +209,7 @@ const Ores: IHarvestable[] = [ respawnLow: 20, respawnHigh: 30, baseChance: 50, - break: 100 + break: 100, }, { objects: SILVER_OBJECTS, @@ -214,7 +219,7 @@ const Ores: IHarvestable[] = [ respawnLow: 30, respawnHigh: 40, baseChance: 40, - break: 100 + break: 100, }, { objects: GOLD_OBJECTS, @@ -224,7 +229,7 @@ const Ores: IHarvestable[] = [ respawnLow: 50, respawnHigh: 70, baseChance: 30, - break: 100 + break: 100, }, { objects: MITHRIL_OBJECTS, @@ -234,7 +239,7 @@ const Ores: IHarvestable[] = [ respawnLow: 90, respawnHigh: 120, baseChance: 20, - break: 100 + break: 100, }, { objects: ADAMANT_OBJECTS, @@ -244,7 +249,7 @@ const Ores: IHarvestable[] = [ respawnLow: 200, respawnHigh: 400, baseChance: 0, - break: 100 + break: 100, }, { objects: RUNITE_OBJECTS, @@ -254,26 +259,26 @@ const Ores: IHarvestable[] = [ respawnLow: 1200, respawnHigh: 1200, baseChance: -10, - break: 100 + break: 100, }, { objects: new Map([[2111, 450]]), items: [ - { itemConfigId: 'rs:uncut_opal', weight: 60 }, // 60/128 - { itemConfigId: 'rs:uncut_jade', weight: 30 }, // 30/128 + { itemConfigId: 'rs:uncut_opal', weight: 60 }, // 60/128 + { itemConfigId: 'rs:uncut_jade', weight: 30 }, // 30/128 { itemConfigId: 'rs:uncut_red_topaz', weight: 15 }, // 15/128 - { itemConfigId: 'rs:uncut_sapphire', weight: 9 }, // 9/128 - { itemConfigId: 'rs:uncut_emerald', weight: 5 }, // 5/128 - { itemConfigId: 'rs:uncut_ruby', weight: 5 }, // 5/128 - { itemConfigId: 'rs:uncut_diamond', weight: 4 } // 4/128 + { itemConfigId: 'rs:uncut_sapphire', weight: 9 }, // 9/128 + { itemConfigId: 'rs:uncut_emerald', weight: 5 }, // 5/128 + { itemConfigId: 'rs:uncut_ruby', weight: 5 }, // 5/128 + { itemConfigId: 'rs:uncut_diamond', weight: 4 }, // 4/128 ], level: 40, experience: 65.0, respawnLow: 200, respawnHigh: 400, baseChance: 28, // Base success chance at level 40 - break: 100 // Always depletes after successful mining - } + break: 100, // Always depletes after successful mining + }, ]; const Trees: IHarvestable[] = [ @@ -285,7 +290,7 @@ const Trees: IHarvestable[] = [ respawnLow: 59, respawnHigh: 98, baseChance: 70, - break: 100 + break: 100, }, { objects: ACHEY_OBJECTS, @@ -295,7 +300,7 @@ const Trees: IHarvestable[] = [ respawnLow: 59, respawnHigh: 98, baseChance: 70, - break: 100 + break: 100, }, { objects: OAK_OBJECTS, @@ -305,7 +310,7 @@ const Trees: IHarvestable[] = [ respawnLow: 14, respawnHigh: 14, baseChance: 50, - break: 100 / 8 + break: 100 / 8, }, { objects: WILLOW_OBJECTS, @@ -315,7 +320,7 @@ const Trees: IHarvestable[] = [ respawnLow: 14, respawnHigh: 14, baseChance: 30, - break: 100 / 8 + break: 100 / 8, }, { objects: TEAK_OBJECTS, @@ -325,7 +330,7 @@ const Trees: IHarvestable[] = [ respawnLow: 15, respawnHigh: 15, baseChance: 0, - break: 100 / 8 + break: 100 / 8, }, { objects: DRAMEN_OBJECTS, @@ -335,7 +340,7 @@ const Trees: IHarvestable[] = [ respawnLow: 0, respawnHigh: 0, baseChance: 100, - break: 0 + break: 0, }, { objects: MAPLE_OBJECTS, @@ -345,7 +350,7 @@ const Trees: IHarvestable[] = [ respawnLow: 59, respawnHigh: 59, baseChance: 0, - break: 100 / 8 + break: 100 / 8, }, { objects: HOLLOW_OBJECTS, @@ -355,7 +360,7 @@ const Trees: IHarvestable[] = [ respawnLow: 43, respawnHigh: 44, baseChance: 0, - break: 100 / 8 + break: 100 / 8, }, { objects: MAHOGANY_OBJECTS, @@ -365,7 +370,7 @@ const Trees: IHarvestable[] = [ respawnLow: 14, respawnHigh: 14, baseChance: -5, - break: 100 / 8 + break: 100 / 8, }, { objects: YEW_OBJECTS, @@ -375,7 +380,7 @@ const Trees: IHarvestable[] = [ respawnLow: 99, respawnHigh: 99, baseChance: -15, - break: 100 / 8 + break: 100 / 8, }, { objects: MAGIC_OBJECTS, @@ -385,7 +390,7 @@ const Trees: IHarvestable[] = [ respawnLow: 199, respawnHigh: 199, baseChance: -25, - break: 100 / 8 + break: 100 / 8, }, { objects: DRAMEN_OBJECTS, @@ -395,7 +400,7 @@ const Trees: IHarvestable[] = [ respawnLow: 0, respawnHigh: 0, baseChance: 100, - break: 0 + break: 0, }, { objects: HOLLOW_OBJECTS, @@ -405,7 +410,7 @@ const Trees: IHarvestable[] = [ respawnLow: 43, respawnHigh: 44, baseChance: 0, - break: 100 / 8 + break: 100 / 8, }, ]; diff --git a/src/engine/world/config/item-ids.ts b/src/engine/world/config/item-ids.ts index b98aefec6..3c3bcf9db 100644 --- a/src/engine/world/config/item-ids.ts +++ b/src/engine/world/config/item-ids.ts @@ -3,7 +3,7 @@ export const itemIds = { ratsTail: 300, burntMeat: 2146, eyeOfNewt: 221, - onion: 1957 + onion: 1957, }, coins: 995, bucket: 1925, @@ -76,11 +76,11 @@ export const itemIds = { rune_pp: 5621, rune_s: 5627, rune_fire_u: 2540, - rune_fire_l: 2541 + rune_fire_l: 2541, }, essence: { pure: 7936, - rune: 1436 + rune: 1436, }, talismans: { air: 1438, @@ -96,7 +96,7 @@ export const itemIds = { law: 1458, soul: 1460, nature: 1462, - elemental: 5516 + elemental: 5516, }, tiaras: { blank: 5525, @@ -136,7 +136,7 @@ export const itemIds = { gold: 2357, mithril: 2359, adamantite: 2361, - runite: 2363 + runite: 2363, }, ores: { clay: 434, @@ -149,7 +149,7 @@ export const itemIds = { gold: 444, mithril: 447, adamantite: 449, - runite: 451 + runite: 451, }, daggers: { bronze: 1205, @@ -352,20 +352,20 @@ export const itemIds = { runite: 9431, }, oilLanternFrames: { - steel: 4540 + steel: 4540, }, studs: { - steel: 2370 + steel: 2370, }, grappleTips: { - mithril: 9415 + mithril: 9415, }, roots: { oak: 6043, willow: 6047, maple: 6047, yew: 6049, - magic: 6051 + magic: 6051, }, logs: { normal: 1511, @@ -373,12 +373,12 @@ export const itemIds = { oak: 1521, willow: 1519, teak: 6333, - dramenbranch:771, + dramenbranch: 771, maple: 1517, bark: 3239, mahogany: 6332, yew: 1515, - magic: 1513 + magic: 1513, }, bowunstrung: { woodshort: 50, @@ -393,7 +393,7 @@ export const itemIds = { yewshort: 68, yewlong: 66, magicshort: 72, - magiclong: 70 + magiclong: 70, }, bowstrung: { woodshort: 841, @@ -408,7 +408,7 @@ export const itemIds = { yewshort: 857, yewlong: 855, magicshort: 861, - magiclong: 859 + magiclong: 859, }, skillCapes: { attack: { @@ -507,6 +507,6 @@ export const itemIds = { air: 1381, fire: 1387, water: 1383, - earth: 1385 - } + earth: 1385, + }, }; diff --git a/src/engine/world/config/object-ids.ts b/src/engine/world/config/object-ids.ts index 0e12b1ec2..a6ce73866 100644 --- a/src/engine/world/config/object-ids.ts +++ b/src/engine/world/config/object-ids.ts @@ -7,7 +7,7 @@ export const objectIds = { depositBox: 9398, shortCuts: { stile: 12982, - fenceNearKharidCows: 9300 + fenceNearKharidCows: 9300, }, ladders: { taverlyDungeonOverworld: 1759, @@ -67,13 +67,11 @@ export const objectIds = { { default: 5903, stump: 1351 }, { default: 5904, stump: 1351 }, ], - archey: [ - { default: 2023, stump: 3371 } - ], + archey: [{ default: 2023, stump: 3371 }], oak: [ { default: 1281, stump: 1356 }, // { default: 3037, stump: 1342 }, // Sigex: dark Oak tutorial island no stump - { default: 8467, stump: 0 } // Farming + { default: 8467, stump: 0 }, // Farming ], willow: [ { default: 1308, stump: 7399 }, @@ -87,9 +85,7 @@ export const objectIds = { { default: 9036, stump: 9037 }, { default: 15062, stump: 9037 }, // Sigex: questionable object, high value ], - dramen: [ - { default: 1292, stump: -1 }, - ], + dramen: [{ default: 1292, stump: -1 }], maple: [ { default: 1307, stump: 7400 }, { default: 4674, stump: 7400 }, @@ -99,9 +95,7 @@ export const objectIds = { { default: 2289, stump: 2310 }, { default: 4060, stump: 4061 }, ], - mahogany: [ - { default: 9034, stump: 9035 }, - ], + mahogany: [{ default: 9034, stump: 9035 }], yew: [ { default: 1309, stump: 7402 }, // { default: 8513, stump: 0 }, // Farming @@ -116,7 +110,7 @@ export const objectIds = { { default: 2108, empty: 450 }, { default: 2109, empty: 451 }, { default: 14904, empty: 14896 }, - { default: 14905, empty: 14897 } + { default: 14905, empty: 14897 }, ], copper: [ { default: 11960, empty: 11555 }, @@ -131,7 +125,7 @@ export const objectIds = { { default: 14907, empty: 14899 }, { default: 14856, empty: 14832 }, { default: 14857, empty: 14833 }, - { default: 14858, empty: 14834 } + { default: 14858, empty: 14834 }, ], tin: [ { default: 11597, empty: 11555 }, @@ -143,7 +137,7 @@ export const objectIds = { { default: 2094, empty: 450 }, { default: 2095, empty: 451 }, { default: 14092, empty: 14894 }, - { default: 14903, empty: 14895 } + { default: 14903, empty: 14895 }, ], iron: [ { default: 11954, empty: 11555 }, @@ -154,7 +148,7 @@ export const objectIds = { { default: 14900, empty: 14892 }, { default: 14901, empty: 14893 }, { default: 14913, empty: 14915 }, - { default: 14914, empty: 14916 } + { default: 14914, empty: 14916 }, ], coal: [ { default: 11963, empty: 11555 }, @@ -167,21 +161,21 @@ export const objectIds = { { default: 2097, empty: 451 }, { default: 14850, empty: 14832 }, { default: 14851, empty: 14833 }, - { default: 14852, empty: 14834 } + { default: 14852, empty: 14834 }, ], silver: [ { default: 11948, empty: 11555 }, { default: 11949, empty: 11556 }, { default: 11950, empty: 11557 }, { default: 2100, empty: 450 }, - { default: 2101, empty: 451 } + { default: 2101, empty: 451 }, ], gold: [ { default: 11951, empty: 11555 }, { default: 11952, empty: 11556 }, { default: 11953, empty: 11557 }, { default: 2098, empty: 450 }, - { default: 2099, empty: 451 } + { default: 2099, empty: 451 }, ], mithril: [ { default: 11945, empty: 11555 }, @@ -194,7 +188,7 @@ export const objectIds = { { default: 2103, empty: 451 }, { default: 14853, empty: 14832 }, { default: 14854, empty: 14833 }, - { default: 14855, empty: 14834 } + { default: 14855, empty: 14834 }, ], adamant: [ { default: 11939, empty: 11552 }, @@ -204,14 +198,14 @@ export const objectIds = { { default: 2105, empty: 451 }, { default: 14862, empty: 14832 }, { default: 14863, empty: 14833 }, - { default: 14864, empty: 14834 } + { default: 14864, empty: 14834 }, ], runite: [ { default: 2106, empty: 450 }, { default: 2107, empty: 451 }, { default: 14859, empty: 14832 }, { default: 14860, empty: 14833 }, - { default: 14861, empty: 14834 } - ] - } + { default: 14861, empty: 14834 }, + ], + }, }; diff --git a/src/engine/world/config/scenery-spawns.ts b/src/engine/world/config/scenery-spawns.ts index 523c1950b..ee22a55ea 100644 --- a/src/engine/world/config/scenery-spawns.ts +++ b/src/engine/world/config/scenery-spawns.ts @@ -1,23 +1,22 @@ -import { logger } from '@runejs/common'; -import { JSON_SCHEMA, load } from 'js-yaml'; import { readFileSync } from 'fs'; +import { logger } from '@runejs/common'; import type { LandscapeObject } from '@runejs/filestore'; +import { JSON_SCHEMA, load } from 'js-yaml'; export function parseScenerySpawns(): LandscapeObject[] { try { logger.info('Parsing scenery spawns...'); - const scenerySpawns = load(readFileSync('data/config/scenery-spawns.yaml', 'utf8'), - { schema: JSON_SCHEMA }) as LandscapeObject[]; + const scenerySpawns = load(readFileSync('data/config/scenery-spawns.yaml', 'utf8'), { schema: JSON_SCHEMA }) as LandscapeObject[]; - if(!scenerySpawns || scenerySpawns.length === 0) { + if (!scenerySpawns || scenerySpawns.length === 0) { throw new Error('Unable to read scenery spawns.'); } logger.info(`${scenerySpawns.length} scenery spawns found.`); return scenerySpawns; - } catch(error) { + } catch (error) { logger.error('Error parsing scenery spawns: ' + error); return []; } diff --git a/src/engine/world/config/songs.ts b/src/engine/world/config/songs.ts index b41b366a3..9dd5ea0b4 100644 --- a/src/engine/world/config/songs.ts +++ b/src/engine/world/config/songs.ts @@ -188,7 +188,7 @@ export const songs = new Map([ ['knightly', 191], ['trinity', 192], ['mellow', 193], - ['brimstail\'s scales', 194], + ["brimstail's scales", 194], ['delrith summoning', 195], ['wally cutscene', 196], ['lament of meiyerditch', 197], @@ -282,11 +282,11 @@ export const songs = new Map([ ['the slayer', 341], ['body parts', 342], ['monster melee', 343], - ['fenkenstrain\'s refrain', 344], + ["fenkenstrain's refrain", 344], ['barking mad', 345], ['goblin game', 346], ['fruits de mer', 347], - ['narnode\'s theme', 348], + ["narnode's theme", 348], ['dynasty', 351], ['scarab', 352], ['shipwrecked', 353], @@ -369,14 +369,14 @@ export const songs = new Map([ ['rat a tat tat', 482], ['the noble rodent', 485], ['bubble and squeak', 489], - ['sarim\'s vermin', 490], + ["sarim's vermin", 490], ['rat hunt', 491], ['the trade parade', 496], ['aye car rum ba', 497], ['blistering barnacles', 498], ['distant land', 501], ['fangs for the memory', 504], - ['pharoah\'s tomb', 505], + ["pharoah's tomb", 505], ['land down under', 506], ['meddling kids', 508], ['corridors of power', 509], @@ -391,7 +391,7 @@ export const songs = new Map([ ['victory is mine', 528], ['woe of the wyvern', 529], ['in the brine', 530], - ['diango\'s little helpers', 532], + ["diango's little helpers", 532], ['roll the bones', 533], ['mind over matter', 534], ['golden touch', 535], @@ -441,12 +441,12 @@ export const songs = new Map([ ['way of the enchanter', 626], ['isle of everywhere', 627], ['the galleon', 630], - ['life\'s a beach!', 631], + ["life's a beach!", 631], ['little cave of horrors', 632], ['on the wing', 633], ['warriors guild', 634], ['ham fisted', 638], ['sigmunds showdown', 640], ['the last shanty', 643], - ['night of the vampyre', 646] + ['night of the vampyre', 646], ]); diff --git a/src/engine/world/config/sound-ids.ts b/src/engine/world/config/sound-ids.ts index e22683af2..bda857f20 100644 --- a/src/engine/world/config/sound-ids.ts +++ b/src/engine/world/config/sound-ids.ts @@ -70,7 +70,7 @@ export const soundIds = { femaleDefence: 506, playerDefence: 516, noArmorHitPlayer: 519, - noArmorHit: 511 - } - } + noArmorHit: 511, + }, + }, }; diff --git a/src/engine/world/config/travel-locations.ts b/src/engine/world/config/travel-locations.ts index 2a25de3be..dccd6c47e 100644 --- a/src/engine/world/config/travel-locations.ts +++ b/src/engine/world/config/travel-locations.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'fs'; -import { JSON_SCHEMA, load } from 'js-yaml'; import { Position } from '@engine/world/position'; +import { JSON_SCHEMA, load } from 'js-yaml'; interface RawTravelLocation { name: string; @@ -15,10 +15,10 @@ export interface TravelLocation { } const readLocations = (): TravelLocation[] => { - const locationData = load( - readFileSync('data/config/travel-locations-data.yaml', 'utf8'), - { schema: JSON_SCHEMA }) as RawTravelLocation[]; - return locationData.map((location) => { + const locationData = load(readFileSync('data/config/travel-locations-data.yaml', 'utf8'), { + schema: JSON_SCHEMA, + }) as RawTravelLocation[]; + return locationData.map(location => { return { name: location.name, key: location.name.toLowerCase(), @@ -30,11 +30,11 @@ const readLocations = (): TravelLocation[] => { export class TravelLocations { public readonly locations: TravelLocation[]; - public constructor () { + public constructor() { this.locations = readLocations(); } - public find (search: string): TravelLocation | null { + public find(search: string): TravelLocation | null { search = search.toLowerCase().trim(); for (const location of this.locations) { if (location.key.indexOf(search) >= 0) { diff --git a/src/engine/world/config/widget.ts b/src/engine/world/config/widget.ts index daa8478d9..4e995e4ce 100644 --- a/src/engine/world/config/widget.ts +++ b/src/engine/world/config/widget.ts @@ -17,7 +17,7 @@ export const widgetScripts = { bankWithdrawNoteMode: 115, acceptAid: 427, areaEffectVolume: 872, - questPoints: 101 + questPoints: 101, }; export interface PlayerWidget { diff --git a/src/engine/world/direction.ts b/src/engine/world/direction.ts index 7707f9dd3..55fc4a7de 100644 --- a/src/engine/world/direction.ts +++ b/src/engine/world/direction.ts @@ -10,54 +10,54 @@ export interface DirectionData { */ export type Direction = 'NORTH' | 'SOUTH' | 'EAST' | 'WEST' | 'NORTHEAST' | 'NORTHWEST' | 'SOUTHEAST' | 'SOUTHWEST'; export const directionData: { [key: string]: DirectionData } = { - 'NORTH': { + NORTH: { index: 1, deltaX: 0, deltaY: 1, - rotation: 1 + rotation: 1, }, - 'SOUTH': { + SOUTH: { index: 6, deltaX: 0, deltaY: -1, - rotation: 3 + rotation: 3, }, - 'EAST': { + EAST: { index: 4, deltaX: 1, deltaY: 0, - rotation: 2 + rotation: 2, }, - 'WEST': { + WEST: { index: 3, deltaX: -1, deltaY: 0, - rotation: 0 + rotation: 0, }, - 'NORTHEAST': { + NORTHEAST: { index: 2, deltaX: 1, deltaY: 1, - rotation: 1 + rotation: 1, }, - 'NORTHWEST': { + NORTHWEST: { index: 0, deltaX: -1, deltaY: 1, - rotation: 0 + rotation: 0, }, - 'SOUTHEAST': { + SOUTHEAST: { index: 7, deltaX: 1, deltaY: -1, - rotation: 2 + rotation: 2, }, - 'SOUTHWEST': { + SOUTHWEST: { index: 5, deltaX: -1, deltaY: -1, - rotation: 3 - } + rotation: 3, + }, }; export const WNES: Direction[] = ['WEST', 'NORTH', 'EAST', 'SOUTH']; diff --git a/src/engine/world/index.ts b/src/engine/world/index.ts index 54f4b96f8..e74ad1030 100644 --- a/src/engine/world/index.ts +++ b/src/engine/world/index.ts @@ -5,7 +5,6 @@ import { World } from '@engine/world/world'; */ export let activeWorld: World; - /** * Creates a new instance of the game world and assigns it to the singleton world variable. */ diff --git a/src/engine/world/instances.ts b/src/engine/world/instances.ts index 1ca389747..d348d6d1c 100644 --- a/src/engine/world/instances.ts +++ b/src/engine/world/instances.ts @@ -1,19 +1,18 @@ -import { Position } from '@engine/world/position'; -import type { WorldItem } from '@engine/world/items/world-item'; -import type { Item } from '@engine/world/items/item'; import type { Player } from '@engine/world/actor/player/player'; -import { schedule } from '@engine/world/task'; -import { CollisionMap } from '@engine/world/map/collision-map'; -import type { LandscapeObject } from '@runejs/filestore'; -import { logger } from '@runejs/common'; import { activeWorld } from '@engine/world/index'; +import type { Item } from '@engine/world/items/item'; +import type { WorldItem } from '@engine/world/items/world-item'; +import { CollisionMap } from '@engine/world/map/collision-map'; +import { Position } from '@engine/world/position'; +import { schedule } from '@engine/world/task'; import { World } from '@engine/world/world'; +import { logger } from '@runejs/common'; +import type { LandscapeObject } from '@runejs/filestore'; /** * Additional configuration info for an item being spawned in an instance. */ interface ItemSpawnConfig { - /** * optional] The original owner of the spawned item. */ @@ -34,7 +33,6 @@ interface ItemSpawnConfig { * A game world chunk that is tied to a specific instance. */ export interface InstancedChunk { - /** * A specific instanced game chunk's collision map. */ @@ -44,14 +42,12 @@ export interface InstancedChunk { * Tile modifications made to this instanced chunk. */ mods: Map; - } /** * Modifications made to a single game tile within an instance. */ export class TileModifications { - /** * New game objects that have been introduced to an instance. */ @@ -73,14 +69,12 @@ export class TileModifications { public get empty(): boolean { return this.spawnedObjects.length === 0 && this.hiddenObjects.length === 0 && this.worldItems.length === 0; } - } /** * A player or group instance within the world. */ export class WorldInstance { - /** * A list of game world chunks that have modifications made to them in this instance. */ @@ -95,8 +89,7 @@ export class WorldInstance { * Creates a new game world instance. * @param instanceId The instanceId to apply to this new world instance. */ - public constructor(public readonly instanceId: string) { - } + public constructor(public readonly instanceId: string) {} /** * Spawns a new world item in this instance. @@ -108,7 +101,7 @@ export class WorldInstance { public spawnWorldItem(item: Item | number, position: Position, config?: ItemSpawnConfig): WorldItem { const { owner, respawns, expires } = config || {}; - if(typeof item === 'number') { + if (typeof item === 'number') { item = { itemId: item, amount: 1 }; } const worldItem: WorldItem = { @@ -118,17 +111,17 @@ export class WorldInstance { owner, expires, respawns, - instance: this + instance: this, }; const { chunk: instancedChunk, mods } = this.getTileModifications(position); - if(owner) { + if (owner) { // If this world item is only visible to one player initially, we setup a timeout to spawn it for all other // players after 100 game cycles. try { owner.outgoingPackets.setWorldItem(worldItem, worldItem.position); - } catch(error) { + } catch (error) { logger.error(`Error spawning world item ${worldItem?.itemId} at ${worldItem?.position?.key}`, error); throw error; } @@ -137,9 +130,9 @@ export class WorldInstance { mods.worldItems.push(worldItem); instancedChunk.mods.set(position.key, mods); - if(owner) { + if (owner) { setTimeout(() => { - if(worldItem.removed) { + if (worldItem.removed) { return; } @@ -150,11 +143,11 @@ export class WorldInstance { this.worldItemAdded(worldItem); } - if(expires) { + if (expires) { // If the world item is set to expire, set up a timeout to remove it from the game world after the // specified number of game cycles. setTimeout(() => { - if(worldItem.removed) { + if (worldItem.removed) { return; } @@ -173,26 +166,26 @@ export class WorldInstance { const chunkMap = this.getInstancedChunk(worldItem.position); const chunkMod = chunkMap.mods.get(worldItem.position.key); - if(!chunkMod) { + if (!chunkMod) { // Object no longer exists return; } - if(chunkMod.worldItems && chunkMod.worldItems.length !== 0) { + if (chunkMod.worldItems && chunkMod.worldItems.length !== 0) { const idx = chunkMod.worldItems.findIndex(i => i.itemId === worldItem.itemId && i.amount === worldItem.amount); - if(idx !== -1) { + if (idx !== -1) { chunkMod.worldItems.splice(idx, 1); } } - if(chunkMod.worldItems.length === 0) { + if (chunkMod.worldItems.length === 0) { this.clearTileIfEmpty(worldItem.position); } worldItem.removed = true; this.worldItemRemoved(worldItem); - if(worldItem.respawns !== undefined) { + if (worldItem.respawns !== undefined) { this.respawnItem(worldItem); } } @@ -209,14 +202,18 @@ export class WorldInstance { await schedule(worldItem.respawns); - this.spawnWorldItem({ - itemId: worldItem.itemId, - amount: worldItem.amount - }, worldItem.position, { - respawns: worldItem.respawns, - owner: worldItem.owner, - expires: worldItem.expires - }); + this.spawnWorldItem( + { + itemId: worldItem.itemId, + amount: worldItem.amount, + }, + worldItem.position, + { + respawns: worldItem.respawns, + owner: worldItem.owner, + expires: worldItem.expires, + }, + ); } /** @@ -230,7 +227,7 @@ export class WorldInstance { const nearbyPlayers = activeWorld.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => { - if(excludePlayer && excludePlayer.equals(player)) { + if (excludePlayer && excludePlayer.equals(player)) { return; } @@ -245,11 +242,9 @@ export class WorldInstance { public worldItemRemoved(worldItem: WorldItem): void { const nearbyPlayers = activeWorld.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; - nearbyPlayers.forEach(player => - player.outgoingPackets.removeWorldItem(worldItem, worldItem.position)); + nearbyPlayers.forEach(player => player.outgoingPackets.removeWorldItem(worldItem, worldItem.position)); } - /** * Temporarily hides a game object from the game world. * @param object The game object to temporarily hide from view. @@ -261,7 +256,6 @@ export class WorldInstance { this.showGameObject(object); } - /** * Spawns a temporary game object within the game world. * @param object The game object to spawn. @@ -283,7 +277,7 @@ export class WorldInstance { * @param newObjectInCache Whether or not the object being added is the original game-cache object. */ public toggleGameObjects(newObject: LandscapeObject, oldObject: LandscapeObject, newObjectInCache: boolean): void { - if(newObjectInCache) { + if (newObjectInCache) { this.showGameObject(newObject); this.despawnGameObject(oldObject); } else { @@ -303,21 +297,21 @@ export class WorldInstance { * remain in it's place (in this instance). */ public async replaceGameObject(newObject: LandscapeObject | number, oldObject: LandscapeObject, respawnTicks?: number): Promise { - if(typeof newObject === 'number') { + if (typeof newObject === 'number') { newObject = { objectId: newObject, x: oldObject.x, y: oldObject.y, level: oldObject.level, type: oldObject.type, - orientation: oldObject.orientation + orientation: oldObject.orientation, } as LandscapeObject; } this.hideGameObject(oldObject); this.spawnGameObject(newObject); - if(respawnTicks !== undefined) { + if (respawnTicks !== undefined) { await schedule(respawnTicks); this.despawnGameObject(newObject as LandscapeObject); this.showGameObject(oldObject); @@ -335,7 +329,7 @@ export class WorldInstance { const { chunk: instancedChunk, mods } = this.getTileModifications(position); - if(mods.spawnedObjects.find(o => o.x === object.x && o.y === object.y && o.level === object.level && o.type === object.type)) { + if (mods.spawnedObjects.find(o => o.x === object.x && o.y === object.y && o.level === object.level && o.type === object.type)) { return; } @@ -357,20 +351,21 @@ export class WorldInstance { const instancedChunk = this.getInstancedChunk(position); const tileModifications = instancedChunk.mods.get(position.key); - if(!tileModifications) { + if (!tileModifications) { // Object no longer exists return; } - if(tileModifications.spawnedObjects && tileModifications.spawnedObjects.length !== 0) { - const idx = tileModifications.spawnedObjects.findIndex(o => o.objectId === object.objectId && - o.type === object.type && o.orientation === object.orientation); - if(idx !== -1) { + if (tileModifications.spawnedObjects && tileModifications.spawnedObjects.length !== 0) { + const idx = tileModifications.spawnedObjects.findIndex( + o => o.objectId === object.objectId && o.type === object.type && o.orientation === object.orientation, + ); + if (idx !== -1) { tileModifications.spawnedObjects.splice(idx, 1); } } - if(tileModifications.spawnedObjects.length === 0) { + if (tileModifications.spawnedObjects.length === 0) { this.clearTileIfEmpty(position); } @@ -408,20 +403,21 @@ export class WorldInstance { const tileModifications = instancedChunk.mods.get(position.key); - if(!tileModifications) { + if (!tileModifications) { // Object no longer exists return; } - if(tileModifications.hiddenObjects && tileModifications.hiddenObjects.length !== 0) { - const idx = tileModifications.hiddenObjects.findIndex(o => o.objectId === object.objectId && - o.type === object.type && o.orientation === object.orientation); - if(idx !== -1) { + if (tileModifications.hiddenObjects && tileModifications.hiddenObjects.length !== 0) { + const idx = tileModifications.hiddenObjects.findIndex( + o => o.objectId === object.objectId && o.type === object.type && o.orientation === object.orientation, + ); + if (idx !== -1) { tileModifications.hiddenObjects.splice(idx, 1); } } - if(tileModifications.hiddenObjects.length === 0) { + if (tileModifications.hiddenObjects.length === 0) { this.clearTileIfEmpty(position); } @@ -437,7 +433,6 @@ export class WorldInstance { */ public getInstancedChunk(worldPosition: Position): InstancedChunk; - /** * Fetch a list of world modifications from this instance. * @param x The X coordinate to find the chunk of. @@ -449,37 +444,37 @@ export class WorldInstance { public getInstancedChunk(worldPositionOrX: Position | number, y?: number, level?: number): InstancedChunk { let chunkPosition: Position | null = null; - if(typeof worldPositionOrX === 'number') { + if (typeof worldPositionOrX === 'number') { const chunk = activeWorld.chunkManager.getChunk({ x: worldPositionOrX, // using ! here because we know that if the first parameter is a number, the other two will be too y: y!, - level: level! + level: level!, }); - if(chunk) { + if (chunk) { chunkPosition = chunk.position; } } else { chunkPosition = activeWorld.chunkManager.getChunkForWorldPosition(worldPositionOrX)?.position || null; } - if(!chunkPosition) { + if (!chunkPosition) { // Chunk not found - fail gracefully logger.error('Failed to find chunk for world position', worldPositionOrX, y, level); logger.error('Something has likely gone horribly wrong!'); return { collisionMap: new CollisionMap(0, 0, 0, { instance: this }), - mods: new Map() + mods: new Map(), }; } - if(!this.chunkModifications.has(chunkPosition.key)) { + if (!this.chunkModifications.has(chunkPosition.key)) { this.chunkModifications.set(chunkPosition.key, { collisionMap: new CollisionMap(chunkPosition.x, chunkPosition.y, chunkPosition.level, { instance: this }), - mods: new Map() + mods: new Map(), }); } @@ -491,13 +486,13 @@ export class WorldInstance { * Fetches the list of tile modifications for a specific game tile in this instance. * @param worldPosition The world position to find the modifications for. */ - public getTileModifications(worldPosition: Position): { chunk: InstancedChunk, mods: TileModifications } { + public getTileModifications(worldPosition: Position): { chunk: InstancedChunk; mods: TileModifications } { const instancedChunk = this.getInstancedChunk(worldPosition); - if(instancedChunk.mods.has(worldPosition.key)) { + if (instancedChunk.mods.has(worldPosition.key)) { return { chunk: instancedChunk, // using ! here because we know it exists - mods: instancedChunk.mods.get(worldPosition.key)! + mods: instancedChunk.mods.get(worldPosition.key)!, }; } @@ -521,7 +516,7 @@ export class WorldInstance { public removePlayer(player: Player): void { this.players.delete(player.username); - if(this.instanceId !== activeWorld.globalInstance.instanceId && this.players.size === 0) { + if (this.instanceId !== activeWorld.globalInstance.instanceId && this.players.size === 0) { this.chunkModifications.clear(); const instancedNpcs = activeWorld.findNpcsByInstance(this.instanceId); instancedNpcs?.forEach(npc => activeWorld.deregisterNpc(npc)); @@ -543,9 +538,8 @@ export class WorldInstance { return; } - if(mods.empty) { + if (mods.empty) { instancedChunk.mods.delete(worldPosition.key); } } - } diff --git a/src/engine/world/items/item-container.ts b/src/engine/world/items/item-container.ts index 213a41fb4..cbb2edea8 100644 --- a/src/engine/world/items/item-container.ts +++ b/src/engine/world/items/item-container.ts @@ -1,11 +1,10 @@ -import type { Item } from './item'; -import { Subject } from 'rxjs'; -import { filestore } from '@server/game/game-server'; -import { hasValueNotNull } from '@engine/util/data'; import { findItem } from '@engine/config/config-handler'; -import { logger } from '@runejs/common'; +import { hasValueNotNull } from '@engine/util/data'; import { fromNote } from '@engine/world/items/item'; - +import { logger } from '@runejs/common'; +import { filestore } from '@server/game/game-server'; +import { Subject } from 'rxjs'; +import type { Item } from './item'; export interface ContainerUpdateEvent { slot?: number; @@ -14,12 +13,12 @@ export interface ContainerUpdateEvent { } export const getItemFromContainer = (itemId: number, slot: number, container: ItemContainer): Item | null => { - if(slot < 0 || slot > container.items.length - 1) { + if (slot < 0 || slot > container.items.length - 1) { return null; } const item = container.items[slot]; - if(!item || item.itemId !== itemId) { + if (!item || item.itemId !== itemId) { return null; } @@ -34,7 +33,6 @@ export const getItemFromContainer = (itemId: number, slot: number, container: It type InventoryMapType = (Item | null)[]; export class ItemContainer { - private readonly _size: number; private readonly _items: InventoryMapType; private readonly _containerUpdated: Subject; @@ -44,15 +42,15 @@ export class ItemContainer { this._items = new Array(size); this._containerUpdated = new Subject(); - for(let i = 0; i < size; i++) { + for (let i = 0; i < size; i++) { this._items[i] = null; } } public clear(fireEvent: boolean = true): void { - this._items.forEach((item, index) => this._items[index] = null); + this._items.forEach((item, index) => (this._items[index] = null)); - if(fireEvent) { + if (fireEvent) { this._containerUpdated.next({ type: 'CLEAR_ALL' }); } } @@ -63,7 +61,8 @@ export class ItemContainer { public amount(item: number | Item): number { const itemId = typeof item === 'number' ? item : item.itemId; - return this._items.map(item => item && item.itemId === itemId ? (item.amount || 0) : 0) + return this._items + .map(item => (item && item.itemId === itemId ? item.amount || 0 : 0)) .reduce((accumulator, currentValue) => accumulator + currentValue); } @@ -73,7 +72,7 @@ export class ItemContainer { * @returns An array of slot numbers. */ public findAll(search: number | Item): number[] { - if(typeof search !== 'number') { + if (typeof search !== 'number') { search = search.itemId; } @@ -86,21 +85,21 @@ export class ItemContainer { const stackable = searchItem.stackable; - if(stackable) { + if (stackable) { const index = this.findIndex(search); - if(!hasValueNotNull(index) || index === -1) { + if (!hasValueNotNull(index) || index === -1) { return []; } else { - return [ index ]; + return [index]; } } else { const slots: number[] = []; - for(let i = 0; i < this.size; i++) { + for (let i = 0; i < this.size; i++) { const item = this.items[i]; - if(item?.itemId === search) { + if (item?.itemId === search) { slots.push(i); } } @@ -110,37 +109,36 @@ export class ItemContainer { } public findIndex(item: number | Item): number { - const itemId = (typeof item === 'number') ? item : item.itemId; + const itemId = typeof item === 'number' ? item : item.itemId; return this._items.findIndex(i => i?.itemId === itemId); } public setAll(items: (Item | null)[], fireEvent: boolean = true): void { - for(let i = 0; i < this._size; i++) { + for (let i = 0; i < this._size; i++) { this._items[i] = items[i]; } - if(fireEvent) { + if (fireEvent) { this._containerUpdated.next({ type: 'SET_ALL' }); } } public set(slot: number, item: Item | null, fireEvent: boolean = true): void { this._items[slot] = item; - if(fireEvent) { + if (fireEvent) { this._containerUpdated.next({ type: 'SET', slot, item }); } } public findItemIndex(item: Item): number { - for(let i = 0; i < this._size; i++) { + for (let i = 0; i < this._size; i++) { const inventoryItem = this._items[i]; if (inventoryItem === null) { continue; } - if(inventoryItem.itemId === item.itemId && - inventoryItem.amount >= item.amount) { + if (inventoryItem.itemId === item.itemId && inventoryItem.amount >= item.amount) { return i; } } @@ -148,12 +146,12 @@ export class ItemContainer { return -1; } - public add(item: number | string | Item, fireEvent: boolean = true): { item: Item, slot: number } | null { + public add(item: number | string | Item, fireEvent: boolean = true): { item: Item; slot: number } | null { if (typeof item === 'number') { item = { itemId: item, amount: 1 } as Item; } else if (typeof item === 'string') { const itemDetails = findItem(item); - if(!itemDetails) { + if (!itemDetails) { logger.warn(`Item ${item} not configured on the server.`); return null; } @@ -173,7 +171,7 @@ export class ItemContainer { const newItem = { itemId: item.itemId, // using ! here because we know the item exists in the inventory - amount: this._items[existingItemIndex]!.amount += item.amount + amount: (this._items[existingItemIndex]!.amount += item.amount), } as Item; this.set(existingItemIndex, newItem, false); @@ -202,7 +200,7 @@ export class ItemContainer { } } - public addStacking(item: number | Item, fireEvent: boolean = true): { item: Item, slot: number } | null { + public addStacking(item: number | Item, fireEvent: boolean = true): { item: Item; slot: number } | null { if (typeof item === 'number') { item = { itemId: item, amount: 1 } as Item; } @@ -213,7 +211,7 @@ export class ItemContainer { const newItem = { itemId: item.itemId, // using ! here because we know the item exists in the inventory - amount: this._items[existingItemIndex]!.amount += item.amount + amount: (this._items[existingItemIndex]!.amount += item.amount), } as Item; this.set(existingItemIndex, newItem, false); @@ -226,7 +224,7 @@ export class ItemContainer { return { item: newItem, slot: existingItemIndex }; } else { const newItemIndex = this.getFirstOpenSlot(); - if(newItemIndex === -1) { + if (newItemIndex === -1) { // Not enough container space return null; } @@ -248,13 +246,13 @@ export class ItemContainer { public removeFirst(item: number | Item, fireEvent: boolean = true): number { const slot = this.findIndex(item); - if(slot === -1) { + if (slot === -1) { return -1; } this._items[slot] = null; - if(fireEvent) { + if (fireEvent) { this._containerUpdated.next({ type: 'REMOVE', slot }); } @@ -265,7 +263,7 @@ export class ItemContainer { const item = this._items[slot]; this._items[slot] = null; - if(fireEvent) { + if (fireEvent) { this._containerUpdated.next({ type: 'REMOVE', slot }); } return item; @@ -281,8 +279,8 @@ export class ItemContainer { public getOpenSlotCount(): number { let count = 0; - for(let i = 0; i < this._size; i++) { - if(!hasValueNotNull(this._items[i])) { + for (let i = 0; i < this._size; i++) { + if (!hasValueNotNull(this._items[i])) { count++; } } @@ -293,8 +291,8 @@ export class ItemContainer { public getOpenSlots(): number[] { const slots: number[] = []; - for(let i = 0; i < this._size; i++) { - if(!hasValueNotNull(this._items[i])) { + for (let i = 0; i < this._size; i++) { + if (!hasValueNotNull(this._items[i])) { slots.push(i); } } @@ -313,14 +311,14 @@ export class ItemContainer { public weight(): number { let weight = 0; - for(const item of this._items) { - if(!item) { + for (const item of this._items) { + if (!item) { continue; } const itemData = findItem(item.itemId); - if(!itemData?.weight) { + if (!itemData?.weight) { continue; } @@ -332,11 +330,11 @@ export class ItemContainer { public canFit(item: Item, everythingStacks: boolean = false): boolean { const itemDefinition = filestore.configStore.itemStore.getItem(item.itemId); - if(!itemDefinition) { - throw new Error(`Item ID ${ item.itemId } not found!`); + if (!itemDefinition) { + throw new Error(`Item ID ${item.itemId} not found!`); } - if(itemDefinition.stackable || everythingStacks || fromNote(item) > -1) { - if(this.has(item.itemId)) { + if (itemDefinition.stackable || everythingStacks || fromNote(item) > -1) { + if (this.has(item.itemId)) { // using ! here because we know that we have the item in the inventory const invItem = this.items[this.findIndex(item.itemId)]!; return invItem.amount + item.amount <= 2147483647; @@ -347,7 +345,6 @@ export class ItemContainer { } } - public get size(): number { return this._size; } @@ -359,5 +356,4 @@ export class ItemContainer { public get containerUpdated(): Subject { return this._containerUpdated; } - } diff --git a/src/engine/world/items/item.ts b/src/engine/world/items/item.ts index 92973b65d..51adfe391 100644 --- a/src/engine/world/items/item.ts +++ b/src/engine/world/items/item.ts @@ -1,7 +1,6 @@ -import { filestore } from '@server/game/game-server'; import { findItem, itemMap, widgets } from '@engine/config/config-handler'; import type { ParentWidget, StaticItemWidget, WidgetBase } from '@runejs/filestore'; - +import { filestore } from '@server/game/game-server'; export interface Item { itemId: number; @@ -10,7 +9,7 @@ export interface Item { function itemInventoryOptions(itemId: number): string[] { const itemDefinition = filestore.configStore.itemStore.getItem(itemId); - if(!itemDefinition) { + if (!itemDefinition) { return []; } @@ -26,7 +25,7 @@ function IsStaticItemWidget(widget: WidgetBase): widget is StaticItemWidget { return 'items' in widget; } -export const getItemOptions = (itemId: number, widget: { widgetId: number, containerId: number }): string[] => { +export const getItemOptions = (itemId: number, widget: { widgetId: number; containerId: number }): string[] => { const widgetDefinition = filestore.widgetStore.decodeWidget(widget.widgetId) as WidgetBase; if (widget.widgetId === widgets.inventory.widgetId) { @@ -41,7 +40,7 @@ export const getItemOptions = (itemId: number, widget: { widgetId: number, conta if (IsParentWidget(widgetDefinition)) { const widgetChild = widgetDefinition.children[widget.containerId]; if (IsStaticItemWidget(widgetChild)) { - optionsWidget = widgetChild + optionsWidget = widgetChild; } } @@ -52,25 +51,25 @@ export const getItemOptions = (itemId: number, widget: { widgetId: number, conta return optionsWidget.options; }; -export const getItemOption = (itemId: number, optionNumber: number, widget: { widgetId: number, containerId: number }): string => { +export const getItemOption = (itemId: number, optionNumber: number, widget: { widgetId: number; containerId: number }): string => { const optionIndex = optionNumber - 1; const options = getItemOptions(itemId, widget); let option = 'option-' + optionNumber; - if(options && options.length >= optionNumber) { - if(options[optionIndex] !== null && options[optionIndex].toLowerCase() !== 'hidden') { + if (options && options.length >= optionNumber) { + if (options[optionIndex] !== null && options[optionIndex].toLowerCase() !== 'hidden') { option = options[optionIndex].toLowerCase(); } } - option = option.replace(/ /g, '-') - if(['wield','wear','equip'].find((s) => s === option)){ + option = option.replace(/ /g, '-'); + if (['wield', 'wear', 'equip'].find(s => s === option)) { option = 'equip'; } return option; }; export function parseItemId(item: number | Item): number { - return (typeof item !== 'number' ? item.itemId : item); + return typeof item !== 'number' ? item.itemId : item; } export function toNote(item: number | Item): number { diff --git a/src/engine/world/items/world-item.ts b/src/engine/world/items/world-item.ts index 6aed29d09..0c85d3498 100644 --- a/src/engine/world/items/world-item.ts +++ b/src/engine/world/items/world-item.ts @@ -1,7 +1,6 @@ -import type { Position } from '@engine/world/position'; import type { Player } from '@engine/world/actor/player/player'; import type { WorldInstance } from '@engine/world/instances'; - +import type { Position } from '@engine/world/position'; export type WorldItem = { itemId: number; @@ -12,4 +11,4 @@ export type WorldItem = { respawns?: number; removed?: boolean; instance: WorldInstance; -} +}; diff --git a/src/engine/world/map/chunk-manager.ts b/src/engine/world/map/chunk-manager.ts index f4724455c..f26cf2000 100644 --- a/src/engine/world/map/chunk-manager.ts +++ b/src/engine/world/map/chunk-manager.ts @@ -1,17 +1,21 @@ -import { Chunk } from './chunk'; -import { Position } from '../position'; import { logger } from '@runejs/common'; -import { filestore } from '@server/game/game-server'; import type { LandscapeFile, LandscapeObject, MapFile } from '@runejs/filestore'; +import { filestore } from '@server/game/game-server'; +import { Position } from '../position'; +import { Chunk } from './chunk'; export class Tile { - public settings: number = 0; public blocked: boolean = false; public bridge: boolean = false; - public constructor(public x: number, public y: number, public level: number, settings?: number) { - if(settings) { + public constructor( + public x: number, + public y: number, + public level: number, + settings?: number, + ) { + if (settings) { this.setSettings(settings); } } @@ -21,7 +25,6 @@ export class Tile { this.blocked = (this.settings & 0x1) === 1; this.bridge = (this.settings & 0x2) === 2; } - } export interface MapRegion { @@ -29,12 +32,10 @@ export interface MapRegion { mapFile: MapFile; } - /** * Controls all of the game world's map chunks. */ export class ChunkManager { - public readonly regionMap: Map = new Map(); private readonly chunkMap: Map; @@ -53,7 +54,7 @@ export class ChunkManager { this.registerMapRegion(mapRegionX, mapRegionY); - if(!regionSettings) { + if (!regionSettings) { return new Tile(position.x, position.y, position.level); } @@ -62,10 +63,10 @@ export class ChunkManager { const tileLevel = position.level; let tileSettings = regionSettings[tileLevel][tileX][tileY]; - if(tileLevel < 3) { + if (tileLevel < 3) { // Check for a bridge tile above the active tile const tileAboveSettings = regionSettings[tileLevel + 1][tileX][tileY]; - if((tileAboveSettings & 0x2) === 2) { + if ((tileAboveSettings & 0x2) === 2) { // Set this tile as walkable if the tile above is a bridge - // This is because the maps are stored with bridges being one level // above where their collision maps need to be @@ -79,7 +80,7 @@ export class ChunkManager { public registerMapRegion(mapRegionX: number, mapRegionY: number): void { const key = `${mapRegionX},${mapRegionY}`; - if(this.regionMap.has(key)) { + if (this.regionMap.has(key)) { // Map region already registered return; } @@ -90,21 +91,21 @@ export class ChunkManager { try { mapFile = filestore.regionStore.getMapFile(mapRegionX, mapRegionY); - } catch(error) { + } catch (error) { logger.error(`Error decoding map file ${mapRegionX},${mapRegionY}`); } try { landscapeFile = filestore.regionStore.getLandscapeFile(mapRegionX, mapRegionY); - } catch(error) { + } catch (error) { logger.error(`Error decoding landscape file ${mapRegionX},${mapRegionY}`); } - if(!mapFile) { + if (!mapFile) { logger.error(`No decoded map file ${mapRegionX},${mapRegionY}`); return; } - if(!landscapeFile) { + if (!landscapeFile) { logger.error(`No decoded landscape file ${mapRegionX},${mapRegionY}`); return; } @@ -116,20 +117,20 @@ export class ChunkManager { } public registerObjects(objects: LandscapeObject[], mapFile: MapFile): void { - if(!objects || objects.length === 0) { + if (!objects || objects.length === 0) { return; } const mapWorldPositionX = (mapFile.regionX & 0xff) * 64; const mapWorldPositionY = mapFile.regionY * 64; - for(const object of objects) { + for (const object of objects) { const position = new Position(object.x, object.y, object.level); const localX = object.x - mapWorldPositionX; const localY = object.y - mapWorldPositionY; - for(let level = 3; level >= 0; level--) { - if((mapFile.tileSettings[level][localX][localY] & 0x2) === 2) { + for (let level = 3; level >= 0; level--) { + if ((mapFile.tileSettings[level][localX][localY] & 0x2) === 2) { // Object is on or underneath a bridge tile and needs to move down one level position.move(object.x, object.y, object.level - 1); } @@ -146,8 +147,8 @@ export class ChunkManager { const mainY = chunk.position.y; const level = chunk.position.level; - for(let x = mainX - 2; x <= mainX + 2; x++) { - for(let y = mainY - 2; y <= mainY + 2; y++) { + for (let x = mainX - 2; x <= mainX + 2; x++) { + for (let y = mainY - 2; y <= mainY + 2; y++) { chunks.push(this.getChunk({ x, y, level })); } } @@ -167,13 +168,13 @@ export class ChunkManager { return this.getChunk({ x: position.chunkX, y: position.chunkY, level: position.level }); } - public getChunk(position: Position | { x: number, y: number, level: number }): Chunk { - if(!(position instanceof Position)) { + public getChunk(position: Position | { x: number; y: number; level: number }): Chunk { + if (!(position instanceof Position)) { position = new Position(position.x, position.y, position.level); } - const pos = (position as Position); - if(this.chunkMap.has(pos.key)) { + const pos = position as Position; + if (this.chunkMap.has(pos.key)) { // using ! here because we know it exists return this.chunkMap.get(pos.key)!; } else { @@ -183,5 +184,4 @@ export class ChunkManager { return chunk; } } - } diff --git a/src/engine/world/map/chunk.ts b/src/engine/world/map/chunk.ts index cf46a6d40..81ad19216 100644 --- a/src/engine/world/map/chunk.ts +++ b/src/engine/world/map/chunk.ts @@ -1,10 +1,10 @@ -import type { Position } from '../position'; -import type { Player } from '../actor/player/player'; -import { CollisionMap } from './collision-map'; -import type { Npc } from '../actor/npc'; +import { activeWorld } from '@engine/world'; import type { WorldItem } from '@engine/world/items/world-item'; import type { LandscapeObject } from '@runejs/filestore'; -import { activeWorld } from '@engine/world'; +import type { Npc } from '../actor/npc'; +import type { Player } from '../actor/player/player'; +import type { Position } from '../position'; +import { CollisionMap } from './collision-map'; interface CustomLandscapeObject { reference?: boolean; @@ -20,7 +20,6 @@ export interface ChunkUpdateItem { * A single map chunk within the game world that keeps track of the entities within it. */ export class Chunk { - private readonly _position: Position; private readonly _players: Player[]; private readonly _npcs: Npc[]; @@ -42,33 +41,32 @@ export class Chunk { } public setFilestoreLandscapeObject(landscapeObject: LandscapeObject): void { - this._filestoreLandscapeObjects.set(`${ landscapeObject.x },${ landscapeObject.y },${ landscapeObject.objectId }`, - landscapeObject); + this._filestoreLandscapeObjects.set(`${landscapeObject.x},${landscapeObject.y},${landscapeObject.objectId}`, landscapeObject); this._collisionMap.markGameObject(landscapeObject, true); } public addPlayer(player: Player): void { - if(this._players.findIndex(p => p.equals(player)) === -1) { + if (this._players.findIndex(p => p.equals(player)) === -1) { this._players.push(player); } } public removePlayer(player: Player): void { const index = this._players.findIndex(p => p.equals(player)); - if(index !== -1) { + if (index !== -1) { this._players.splice(index, 1); } } public addNpc(npc: Npc): void { - if(this._npcs.findIndex(n => n.equals(npc)) === -1) { + if (this._npcs.findIndex(n => n.equals(npc)) === -1) { this._npcs.push(npc); } } public removeNpc(npc: Npc): void { const index = this._npcs.findIndex(n => n.equals(npc)); - if(index !== -1) { + if (index !== -1) { this._npcs.splice(index, 1); } } @@ -78,8 +76,7 @@ export class Chunk { } public equals(chunk: Chunk): boolean { - return this.position.x === chunk.position.x && this.position.y === chunk.position.y - && this.position.level === chunk.position.level; + return this.position.x === chunk.position.x && this.position.y === chunk.position.y && this.position.level === chunk.position.level; } public get position(): Position { diff --git a/src/engine/world/map/collision-map.ts b/src/engine/world/map/collision-map.ts index 2bef5b482..fa48d9c36 100644 --- a/src/engine/world/map/collision-map.ts +++ b/src/engine/world/map/collision-map.ts @@ -1,15 +1,14 @@ -import type { Chunk } from './chunk'; -import { filestore } from '@server/game/game-server'; -import type { WorldInstance } from '@engine/world/instances'; -import type { LandscapeObject } from '@runejs/filestore'; import { activeWorld } from '@engine/world'; +import type { WorldInstance } from '@engine/world/instances'; import { logger } from '@runejs/common'; +import type { LandscapeObject } from '@runejs/filestore'; +import { filestore } from '@server/game/game-server'; +import type { Chunk } from './chunk'; /** * A map of collision masks for a chunk within the game world. */ export class CollisionMap { - private heightLevel: number; private x: number; private y: number; @@ -21,7 +20,7 @@ export class CollisionMap { private chunk: Chunk | undefined; private instance: WorldInstance | undefined; - public constructor(x: number, y: number, heightLevel: number, options?: { chunk?: Chunk, instance?: WorldInstance }) { + public constructor(x: number, y: number, heightLevel: number, options?: { chunk?: Chunk; instance?: WorldInstance }) { this.heightLevel = heightLevel; this.x = x; this.y = y; @@ -32,7 +31,7 @@ export class CollisionMap { this.chunk = options?.chunk; this.instance = options?.instance; this._adjacency = new Array(this.sizeX); - for(let i = 0; i < this.sizeX; i++) { + for (let i = 0; i < this.sizeX; i++) { this._adjacency[i] = new Array(this.sizeY); } this.reset(); @@ -50,16 +49,23 @@ export class CollisionMap { return; } - if(objectDetails.solid) { - if(objectType === 22) { - if(objectDetails.hasOptions) { + if (objectDetails.solid) { + if (objectType === 22) { + if (objectDetails.hasOptions) { this.markBlocked(x, y, mark); } - } else if(objectType >= 9) { - this.markSolidOccupant(x, y, objectDetails.rendering.sizeX, objectDetails.rendering.sizeY, - objectOrientation, objectDetails.nonWalkable, mark); - } else if(objectType >= 0 && objectType <= 3) { - if(mark) { + } else if (objectType >= 9) { + this.markSolidOccupant( + x, + y, + objectDetails.rendering.sizeX, + objectDetails.rendering.sizeY, + objectOrientation, + objectDetails.nonWalkable, + mark, + ); + } else if (objectType >= 0 && objectType <= 3) { + if (mark) { this.markWall(x, y, objectType, objectOrientation, objectDetails.nonWalkable); } else { this.unmarkWall(x, y, objectType, objectOrientation, objectDetails.nonWalkable); @@ -69,8 +75,8 @@ export class CollisionMap { } public reset(): void { - for(let x = 0; x < this.sizeX; x++) { - for(let y = 0; y < this.sizeY; y++) { + for (let x = 0; x < this.sizeX; x++) { + for (let y = 0; y < this.sizeY; y++) { this._adjacency[x][y] = this.chunk ? 0 : null; } } @@ -80,118 +86,118 @@ export class CollisionMap { x -= this._insetX; y -= this._insetY; - if(type == 0) { - if(rotation == 0) { + if (type == 0) { + if (rotation == 0) { this.set(x, y, 128); this.set(x - 1, y, 8); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 2); this.set(x, y + 1, 32); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 8); this.set(x + 1, y, 128); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 32); this.set(x, y - 1, 2); } } - if(type == 1 || type == 3) { - if(rotation == 0) { + if (type == 1 || type == 3) { + if (rotation == 0) { this.set(x, y, 1); this.set(x - 1, y + 1, 16); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 4); this.set(x + 1, y + 1, 64); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 16); this.set(x + 1, y - 1, 1); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 64); this.set(x - 1, y - 1, 4); } } - if(type == 2) { - if(rotation == 0) { + if (type == 2) { + if (rotation == 0) { this.set(x, y, 130); this.set(x - 1, y, 8); this.set(x, y + 1, 32); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 10); this.set(x, y + 1, 32); this.set(x + 1, y, 128); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 40); this.set(x + 1, y, 128); this.set(x, y - 1, 2); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 160); this.set(x, y - 1, 2); this.set(x - 1, y, 8); } } - if(walkable) { - if(type == 0) { - if(rotation == 0) { + if (walkable) { + if (type == 0) { + if (rotation == 0) { this.set(x, y, 0x10000); this.set(x - 1, y, 4096); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 1024); this.set(x, y + 1, 16384); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 4096); this.set(x + 1, y, 0x10000); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 16384); this.set(x, y - 1, 1024); } } - if(type == 1 || type == 3) { - if(rotation == 0) { + if (type == 1 || type == 3) { + if (rotation == 0) { this.set(x, y, 512); this.set(x - 1, y + 1, 8192); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 2048); this.set(x + 1, y + 1, 32768); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 8192); this.set(x + 1, y - 1, 512); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 32768); this.set(x - 1, y - 1, 2048); } } - if(type == 2) { - if(rotation == 0) { + if (type == 2) { + if (rotation == 0) { this.set(x, y, 0x10400); this.set(x - 1, y, 4096); this.set(x, y + 1, 16384); } - if(rotation == 1) { + if (rotation == 1) { this.set(x, y, 5120); this.set(x, y + 1, 16384); this.set(x + 1, y, 0x10000); } - if(rotation == 2) { + if (rotation == 2) { this.set(x, y, 20480); this.set(x + 1, y, 0x10000); this.set(x, y - 1, 1024); } - if(rotation == 3) { + if (rotation == 3) { this.set(x, y, 0x14000); this.set(x, y - 1, 1024); this.set(x - 1, y, 4096); @@ -203,118 +209,118 @@ export class CollisionMap { public unmarkWall(x: number, y: number, position: number, rotation: number, impenetrable: boolean): void { x -= this._insetX; y -= this._insetY; - if(position == 0) { - if(rotation == 0) { + if (position == 0) { + if (rotation == 0) { this.unset(x, y, 128); this.unset(x - 1, y, 8); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 2); this.unset(x, y + 1, 32); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 8); this.unset(x + 1, y, 128); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 32); this.unset(x, y - 1, 2); } } - if(position == 1 || position == 3) { - if(rotation == 0) { + if (position == 1 || position == 3) { + if (rotation == 0) { this.unset(x, y, 1); this.unset(x - 1, y + 1, 16); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 4); this.unset(x + 1, y + 1, 64); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 16); this.unset(x + 1, y - 1, 1); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 64); this.unset(x - 1, y - 1, 4); } } - if(position == 2) { - if(rotation == 0) { + if (position == 2) { + if (rotation == 0) { this.unset(x, y, 130); this.unset(x - 1, y, 8); this.unset(x, y + 1, 32); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 10); this.unset(x, y + 1, 32); this.unset(x + 1, y, 128); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 40); this.unset(x + 1, y, 128); this.unset(x, y - 1, 2); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 160); this.unset(x, y - 1, 2); this.unset(x - 1, y, 8); } } - if(impenetrable) { - if(position == 0) { - if(rotation == 0) { + if (impenetrable) { + if (position == 0) { + if (rotation == 0) { this.unset(x, y, 0x10000); this.unset(x - 1, y, 4096); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 1024); this.unset(x, y + 1, 16384); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 4096); this.unset(x + 1, y, 0x10000); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 16384); this.unset(x, y - 1, 1024); } } - if(position == 1 || position == 3) { - if(rotation == 0) { + if (position == 1 || position == 3) { + if (rotation == 0) { this.unset(x, y, 512); this.unset(x - 1, y + 1, 8192); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 2048); this.unset(x + 1, y + 1, 32768); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 8192); this.unset(x + 1, y - 1, 512); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 32768); this.unset(x - 1, y - 1, 2048); } } - if(position == 2) { - if(rotation == 0) { + if (position == 2) { + if (rotation == 0) { this.unset(x, y, 0x10400); this.unset(x - 1, y, 4096); this.unset(x, y + 1, 16384); } - if(rotation == 1) { + if (rotation == 1) { this.unset(x, y, 5120); this.unset(x, y + 1, 16384); this.unset(x + 1, y, 0x10000); } - if(rotation == 2) { + if (rotation == 2) { this.unset(x, y, 20480); this.unset(x + 1, y, 0x10000); this.unset(x, y - 1, 1024); } - if(rotation == 3) { + if (rotation == 3) { this.unset(x, y, 0x14000); this.unset(x, y - 1, 1024); this.unset(x - 1, y, 4096); @@ -323,24 +329,32 @@ export class CollisionMap { } } - public markSolidOccupant(occupantX: number, occupantY: number, width: number, height: number, rotation: number, walkable: boolean, mark: boolean): void { + public markSolidOccupant( + occupantX: number, + occupantY: number, + width: number, + height: number, + rotation: number, + walkable: boolean, + mark: boolean, + ): void { let occupied = 256; - if(walkable) { + if (walkable) { occupied += 0x20000; } occupantX -= this._insetX; occupantY -= this._insetY; - if(rotation === 1 || rotation === 3) { + if (rotation === 1 || rotation === 3) { const off = width; width = height; height = off; } - for(let x = occupantX; x < occupantX + width; x++) { - for(let y = occupantY; y < occupantY + height; y++) { - if(mark) { + for (let x = occupantX; x < occupantX + width; x++) { + for (let y = occupantY; y < occupantY + height; y++) { + if (mark) { this.set(x, y, occupied); } else { this.unset(x, y, occupied); @@ -353,11 +367,11 @@ export class CollisionMap { x -= this._insetX; y -= this._insetY; - if(this._adjacency[x][y] === null) { + if (this._adjacency[x][y] === null) { this._adjacency[x][y] = 0; } - if(mark) { + if (mark) { // @ts-ignore this._adjacency[x][y] |= 0x200000; } else { @@ -372,29 +386,29 @@ export class CollisionMap { let offsetX = 0; let offsetY = 0; - if(x < 0) { + if (x < 0) { offsetX = -1; x = 8 + x; - } else if(x > 7) { + } else if (x > 7) { offsetX = 1; x = x - 8; } - if(y < 0) { + if (y < 0) { offsetY = -1; y = 8 + y; - } else if(y > 7) { + } else if (y > 7) { offsetY = 1; y = y - 8; } - if(offsetX != 0 || offsetY != 0) { + if (offsetX != 0 || offsetY != 0) { this.getSiblingCollisionMap(offsetX, offsetY)?.set(x, y, flag); outOfBounds = true; } - if(!outOfBounds) { - if(this._adjacency[x][y] === null) { + if (!outOfBounds) { + if (this._adjacency[x][y] === null) { this._adjacency[x][y] = 0; } @@ -406,24 +420,24 @@ export class CollisionMap { public unset(x: number, y: number, flag: number): void { let outOfBounds = false; - if(x < 0) { + if (x < 0) { this.getSiblingCollisionMap(-1, 0)?.unset(7, y, flag); outOfBounds = true; - } else if(x > 7) { + } else if (x > 7) { this.getSiblingCollisionMap(1, 0)?.unset(0, y, flag); outOfBounds = true; } - if(y < 0) { + if (y < 0) { this.getSiblingCollisionMap(0, -1)?.unset(x, 7, flag); outOfBounds = true; - } else if(y > 7) { + } else if (y > 7) { this.getSiblingCollisionMap(0, 1)?.unset(x, 0, flag); outOfBounds = true; } - if(!outOfBounds) { - if(this._adjacency[x][y] === null) { + if (!outOfBounds) { + if (this._adjacency[x][y] === null) { this._adjacency[x][y] = 0; } @@ -433,16 +447,15 @@ export class CollisionMap { } public getSiblingCollisionMap(offsetX: number, offsetY: number): CollisionMap | null { - if(this.chunk) { + if (this.chunk) { const offsetChunk: Chunk = activeWorld.chunkManager.getChunk({ x: this.chunk.position.x + offsetX, y: this.chunk.position.y + offsetY, - level: this.heightLevel + level: this.heightLevel, }); return offsetChunk.collisionMap; - } else if(this.instance) { - const instanceChunk = this.instance.getInstancedChunk(this.x + offsetX, - this.y + offsetY, this.heightLevel); + } else if (this.instance) { + const instanceChunk = this.instance.getInstancedChunk(this.x + offsetX, this.y + offsetY, this.heightLevel); return instanceChunk.collisionMap; } diff --git a/src/engine/world/map/region.ts b/src/engine/world/map/region.ts index 78ad218b4..ef33fc75f 100644 --- a/src/engine/world/map/region.ts +++ b/src/engine/world/map/region.ts @@ -18,14 +18,12 @@ export type RegionSizeMap = { * A map of region types to tile sizes. */ export const regionSizes: RegionSizeMap = { - 'mapfile': 104, - 'region': 64, - 'chunk': 8 + mapfile: 104, + region: 64, + chunk: 8, }; - export abstract class ConstructedChunk { - public orientation: number; protected constructor(rotation: number = 0) { @@ -37,7 +35,6 @@ export abstract class ConstructedChunk { public get templatePosition(): Position { return this.getTemplatePosition(); } - } export interface ConstructedRegion { @@ -47,89 +44,78 @@ export interface ConstructedRegion { drawOffsetY?: number; } - - - -export const getTemplateRotatedX = (orientation: number, localX: number, localY: number, - sizeX: number = 1, sizeY: number = 1): number => { - if(orientation === 1 || orientation === 3) { +export const getTemplateRotatedX = (orientation: number, localX: number, localY: number, sizeX: number = 1, sizeY: number = 1): number => { + if (orientation === 1 || orientation === 3) { const i = sizeX; sizeX = sizeY; sizeY = i; } - if(orientation === 0) { + if (orientation === 0) { return localX; } - if(orientation === 1) { + if (orientation === 1) { return 7 - (localY - sizeY + 1); } - if(orientation === 2) { + if (orientation === 2) { return 7 - (localX + sizeX + 1); } return localY; }; -export const getTemplateRotatedY = (orientation: number, localX: number, localY: number, - sizeX: number = 1, sizeY: number = 1): number => { - if(orientation === 1 || orientation === 3) { +export const getTemplateRotatedY = (orientation: number, localX: number, localY: number, sizeX: number = 1, sizeY: number = 1): number => { + if (orientation === 1 || orientation === 3) { const i = sizeX; sizeX = sizeY; sizeY = i; } - if(orientation === 0) { + if (orientation === 0) { return localY; } - if(orientation === 1) { + if (orientation === 1) { return localX; } - if(orientation === 2) { + if (orientation === 2) { return 7 - (localY + sizeY + 1); } return 7 - (localX - sizeX + 1); }; - - - - - - -export const getTemplateLocalX = (orientation: number, localX: number, localY: number, - sizeX: number = 1, sizeY: number = 1): number => { - if(orientation === 2) { +export const getTemplateLocalX = (orientation: number, localX: number, localY: number, sizeX: number = 1, sizeY: number = 1): number => { + if (orientation === 2) { const i = sizeX; sizeX = sizeY; sizeY = i; } - if(orientation === 0) { + if (orientation === 0) { return localX; - } else if(orientation === 1) { + } else if (orientation === 1) { return 7 - (localY + sizeY) + 1; - } else if(orientation === 2) { + } else if (orientation === 2) { return 7 - (localX + sizeX) + 1; - } else { // 3 + } else { + // 3 return localY; } }; -export const getTemplateLocalY = (orientation: number, localX: number, localY: number, - sizeX: number = 1, sizeY: number = 1): number => { - if(orientation === 2) { +export const getTemplateLocalY = (orientation: number, localX: number, localY: number, sizeX: number = 1, sizeY: number = 1): number => { + if (orientation === 2) { const i = sizeX; sizeX = sizeY; sizeY = i; } - if(orientation === 0) { + if (orientation === 0) { return localY; - } else if(orientation === 1) { + } else if (orientation === 1) { return localX; - } else if(orientation === 2) { + } else if (orientation === 2) { return 7 - (localY + sizeY) + 1; - } else { // 3 + } else { + // 3 return 7 - (localX + sizeX) + 1; } }; diff --git a/src/engine/world/position.ts b/src/engine/world/position.ts index bb516394d..9a22576d6 100644 --- a/src/engine/world/position.ts +++ b/src/engine/world/position.ts @@ -1,8 +1,8 @@ import type { Direction } from '@engine/world/direction'; import { directionData } from '@engine/world/direction'; -import { filestore } from '@server/game/game-server'; -import type { LandscapeObject } from '@runejs/filestore'; import { logger } from '@runejs/common'; +import type { LandscapeObject } from '@runejs/filestore'; +import { filestore } from '@server/game/game-server'; const directionDeltaX = [-1, 0, 1, -1, 1, -1, 0, 1]; const directionDeltaY = [1, 1, 1, 0, 0, -1, -1, -1]; @@ -24,7 +24,6 @@ export class Coords { * Represents a single position, or coordinate, within the game world. */ export class Position { - public metadata: { [key: string]: any } = {}; private _x: number; private _y: number; @@ -34,7 +33,7 @@ export class Position { public constructor(coords: Coords); public constructor(x: number, y: number, level?: number); public constructor(arg0: number | Coords | Position, y?: number, level?: number) { - if(typeof arg0 === 'number') { + if (typeof arg0 === 'number') { // using ! here, because we know that if arg0 is a number, then y and level are numbers this.move(arg0, y!, level); } else { @@ -50,7 +49,7 @@ export class Position { public withinInteractionDistance(position: Position, minimumDistance?: number): boolean; public withinInteractionDistance(target: LandscapeObject | Position, minimumDistance?: number): boolean; public withinInteractionDistance(target: LandscapeObject | Position, minimumDistance: number = 1): boolean { - if(target instanceof Position) { + if (target instanceof Position) { return this.distanceBetween(target) <= minimumDistance; } else { const definition = filestore.configStore.objectStore.getObject(target.objectId); @@ -64,25 +63,25 @@ export class Position { let width = definition?.rendering?.sizeX || 1; let height = definition?.rendering?.sizeY || 1; - if(width === undefined || width === null || width < 1) { + if (width === undefined || width === null || width < 1) { width = 1; } - if(height === undefined || height === null || height < 1) { + if (height === undefined || height === null || height < 1) { height = 1; } - if(width === 1 && height === 1) { + if (width === 1 && height === 1) { return this.distanceBetween(new Position(occupantX, occupantY, target.level)) <= minimumDistance; } else { - if(target.orientation === 1 || target.orientation === 3) { + if (target.orientation === 1 || target.orientation === 3) { const off = width; width = height; height = off; } - for(let x = occupantX; x < occupantX + width; x++) { - for(let y = occupantY; y < occupantY + height; y++) { - if(this.distanceBetween(new Position(x, y, target.level)) <= minimumDistance) { + for (let x = occupantX; x < occupantX + width; x++) { + for (let y = occupantY; y < occupantY + height; y++) { + if (this.distanceBetween(new Position(x, y, target.level)) <= minimumDistance) { return true; } } @@ -98,7 +97,7 @@ export class Position { * @param position The game world position to check the distance of. */ public withinViewDistance(position: Position): boolean { - if(position.level !== this.level) { + if (position.level !== this.level) { return false; } @@ -115,7 +114,7 @@ export class Position { * @param checkPlane Whether or not to check if the position is within the same plane. Defaults to true. */ public within(min: Position, max: Position, checkPlane: boolean = true): boolean { - if(checkPlane && (min.level !== max.level || max.level !== this.level)) { + if (checkPlane && (min.level !== max.level || max.level !== this.level)) { return false; } @@ -126,7 +125,7 @@ export class Position { this._x = x; this._y = y; - if(level === undefined) { + if (level === undefined) { this._level = 0; } else { this._level = level; @@ -135,8 +134,8 @@ export class Position { return this; } - public equalsIgnoreLevel(position: Position | { x: number, y: number }): boolean { - if(!(position instanceof Position)) { + public equalsIgnoreLevel(position: Position | { x: number; y: number }): boolean { + if (!(position instanceof Position)) { position = new Position(position.x, position.y); } @@ -152,15 +151,15 @@ export class Position { } public step(steps: number, direction: Direction): Position { - return new Position(this.x + (steps * directionData[direction].deltaX), this.y + (steps * directionData[direction].deltaY), this.level); + return new Position(this.x + steps * directionData[direction].deltaX, this.y + steps * directionData[direction].deltaY, this.level); } public copy(): Position { return new Position(this._x, this._y, this._level); } - public equals(position: Position | { x: number, y: number, level: number }): boolean { - if(!(position instanceof Position)) { + public equals(position: Position | { x: number; y: number; level: number }): boolean { + if (!(position instanceof Position)) { position = new Position(position.x, position.y, position.level); } @@ -209,7 +208,7 @@ export class Position { return { x: this._x, y: this._y, - level: this._level + level: this._level, }; } @@ -264,5 +263,4 @@ export class Position { public get key(): string { return `${this.x},${this.y},${this.level}`; } - } diff --git a/src/engine/world/skill-util/harvest-roll.ts b/src/engine/world/skill-util/harvest-roll.ts index 87ab0aa97..001fa5022 100644 --- a/src/engine/world/skill-util/harvest-roll.ts +++ b/src/engine/world/skill-util/harvest-roll.ts @@ -30,7 +30,6 @@ export function rollBirdsNestType(): Item { return { itemId: item.gameId, amount: 1 }; } - export function rollGemType(): Item { const roll = randomBetween(0, 3); let itemConfigId; diff --git a/src/engine/world/skill-util/harvest-skill.ts b/src/engine/world/skill-util/harvest-skill.ts index ae097a2ef..b138b64fe 100644 --- a/src/engine/world/skill-util/harvest-skill.ts +++ b/src/engine/world/skill-util/harvest-skill.ts @@ -1,10 +1,10 @@ +import { findItem } from '@engine/config/config-handler'; import type { Player } from '@engine/world/actor/player/player'; -import type { IHarvestable } from '@engine/world/config/harvestable-object'; -import { soundIds } from '@engine/world/config/sound-ids'; import { Skill } from '@engine/world/actor/skills'; import type { HarvestTool } from '@engine/world/config/harvest-tool'; import { getBestAxe } from '@engine/world/config/harvest-tool'; -import { findItem } from '@engine/config/config-handler'; +import type { IHarvestable } from '@engine/world/config/harvestable-object'; +import { soundIds } from '@engine/world/config/sound-ids'; import { logger } from '@runejs/common'; /** diff --git a/src/engine/world/sound/music.ts b/src/engine/world/sound/music.ts index a28c6917b..5ec0c86e5 100644 --- a/src/engine/world/sound/music.ts +++ b/src/engine/world/sound/music.ts @@ -1,15 +1,15 @@ export enum MusicPlayerMode { MANUAL = 0, - AUTO = 1 + AUTO = 1, } export enum MusicPlayerLoopMode { ENABLED = 0, - DISABLED = 1 + DISABLED = 1, } export enum MusicTabButtonIds { AUTO_BUTTON_ID = 180, MANUAL_BUTTON_ID = 181, - LOOP_BUTTON_ID = 251 + LOOP_BUTTON_ID = 251, } diff --git a/src/engine/world/world.ts b/src/engine/world/world.ts index 26e20836d..1975c6d34 100644 --- a/src/engine/world/world.ts +++ b/src/engine/world/world.ts @@ -1,33 +1,32 @@ import Quadtree from 'quadtree-lib'; -import { v4 } from 'uuid'; -import { lastValueFrom, Subject } from 'rxjs'; +import { Subject, lastValueFrom } from 'rxjs'; import { take } from 'rxjs/operators'; +import { v4 } from 'uuid'; import { logger } from '@runejs/common'; import type { LandscapeObject } from '@runejs/filestore'; -import { isPlayer } from './actor/util'; -import type { Actor } from '@engine/world/actor/actor'; -import { ChunkManager } from '@engine/world/map/chunk-manager'; -import { Player } from '@engine/world/actor/player/player'; -import { Npc } from '@engine/world/actor/npc'; -import { Position } from '@engine/world/position'; -import type { Task } from '@engine/task/task'; import { loadActionFiles } from '@engine/action/loader'; -import { findObject, itemSpawns, findItem, npcSpawns, findNpc } from '@engine/config/config-handler'; +import { findItem, findNpc, findObject, itemSpawns, npcSpawns } from '@engine/config/config-handler'; import { NpcSpawn } from '@engine/config/npc-spawn-config'; import { loadPlugins } from '@engine/plugins/loader'; +import type { Task } from '@engine/task/task'; import { TaskScheduler } from '@engine/task/task-scheduler'; import { activeWorld } from '@engine/world'; +import type { Actor } from '@engine/world/actor/actor'; +import { Npc } from '@engine/world/actor/npc'; +import { Player } from '@engine/world/actor/player/player'; import { ExamineCache } from '@engine/world/config/examine-data'; import { parseScenerySpawns } from '@engine/world/config/scenery-spawns'; import { TravelLocations } from '@engine/world/config/travel-locations'; +import type { Direction } from '@engine/world/direction'; import { WorldInstance } from '@engine/world/instances'; +import { ChunkManager } from '@engine/world/map/chunk-manager'; import type { ConstructedRegion } from '@engine/world/map/region'; import { getTemplateLocalX, getTemplateLocalY } from '@engine/world/map/region'; +import { Position } from '@engine/world/position'; import { schedule } from '@engine/world/task'; -import type { Direction } from '@engine/world/direction'; - +import { isPlayer } from './actor/util'; export interface QuadtreeKey { x: number; @@ -39,7 +38,6 @@ export interface QuadtreeKey { * Controls the game world and all entities within it. */ export class World { - public static readonly MAX_PLAYERS = 1600; public static readonly MAX_NPCS = 30000; public static readonly TICK_LENGTH = 600; @@ -62,11 +60,11 @@ export class World { this.scenerySpawns = parseScenerySpawns(); this.playerTree = new Quadtree({ width: 10000, - height: 10000 + height: 10000, }); this.npcTree = new Quadtree({ width: 10000, - height: 10000 + height: 10000, }); this.setupWorldTick(); @@ -104,18 +102,21 @@ export class World { * @param objectId The game ID of the object. * @param objectPosition The game world position that the object is expected at. */ - public findObjectAtLocation(actor: Actor, objectId: number, - objectPosition: Position): { object: LandscapeObject | null, cacheOriginal: boolean } { + public findObjectAtLocation( + actor: Actor, + objectId: number, + objectPosition: Position, + ): { object: LandscapeObject | null; cacheOriginal: boolean } { const x = objectPosition.x; const y = objectPosition.y; const objectChunk = this.chunkManager.getChunkForWorldPosition(objectPosition); let customMap = false; - if(isPlayer(actor) && actor.metadata.customMap) { + if (isPlayer(actor) && actor.metadata.customMap) { customMap = true; const templateMapObject = this.findCustomMapObject(actor, objectId, objectPosition); - if(templateMapObject) { + if (templateMapObject) { return { object: templateMapObject, cacheOriginal: true }; } } @@ -125,7 +126,7 @@ export class World { let tileModifications; let personalTileModifications; - if(isPlayer(actor)) { + if (isPlayer(actor)) { const instance = actor.instance; if (!instance) { @@ -139,37 +140,41 @@ export class World { } let landscapeObject = customMap ? null : objectChunk.getFilestoreLandscapeObject(objectId, objectPosition); - if(!landscapeObject) { - const tileObjects = [ ...tileModifications.mods.spawnedObjects ]; + if (!landscapeObject) { + const tileObjects = [...tileModifications.mods.spawnedObjects]; - if(isPlayer(actor)) { + if (isPlayer(actor)) { tileObjects.push(...personalTileModifications.mods.spawnedObjects); } - landscapeObject = tileObjects.find(spawnedObject => - spawnedObject.objectId === objectId && spawnedObject.x === x && spawnedObject.y === y) || null; + landscapeObject = + tileObjects.find(spawnedObject => spawnedObject.objectId === objectId && spawnedObject.x === x && spawnedObject.y === y) || + null; cacheOriginal = false; - if(!landscapeObject) { + if (!landscapeObject) { return { object: null, cacheOriginal: false }; } } - const hiddenTileObjects = [ ...tileModifications.mods.hiddenObjects ]; + const hiddenTileObjects = [...tileModifications.mods.hiddenObjects]; - if(isPlayer(actor)) { + if (isPlayer(actor)) { hiddenTileObjects.push(...personalTileModifications.mods.hiddenObjects); } - if(hiddenTileObjects.findIndex(spawnedObject => - spawnedObject.objectId === objectId && spawnedObject.x === x && spawnedObject.y === y) !== -1) { + if ( + hiddenTileObjects.findIndex( + spawnedObject => spawnedObject.objectId === objectId && spawnedObject.x === x && spawnedObject.y === y, + ) !== -1 + ) { return { object: null, cacheOriginal: false }; } return { object: landscapeObject, - cacheOriginal + cacheOriginal, }; } @@ -180,15 +185,15 @@ export class World { * @param objectPosition The position of the copied object to find the template of. */ public findCustomMapObject(actor: Actor, objectId: number, objectPosition: Position): LandscapeObject | null { - const map = actor?.metadata?.customMap as ConstructedRegion || null; + const map = (actor?.metadata?.customMap as ConstructedRegion) || null; - if(!map) { + if (!map) { return null; } const objectConfig = findObject(objectId); - if(!objectConfig) { + if (!objectConfig) { return null; } @@ -209,18 +214,33 @@ export class World { const mapTemplateWorldX = tileX; const mapTemplateWorldY = tileY; - const mapTemplateChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(mapTemplateWorldX, mapTemplateWorldY, objectPosition.level)); - - const templateLocalX = getTemplateLocalX(tileOrientation, objectLocalX, objectLocalY, - objectConfig?.rendering?.sizeX || 1, objectConfig?.rendering?.sizeY || 1); - const templateLocalY = getTemplateLocalY(tileOrientation, objectLocalX, objectLocalY, - objectConfig?.rendering?.sizeX || 1, objectConfig?.rendering?.sizeY || 1); - - const templateObjectPosition = new Position(mapTemplateWorldX + templateLocalX, - mapTemplateWorldY + templateLocalY, objectPosition.level); + const mapTemplateChunk = activeWorld.chunkManager.getChunkForWorldPosition( + new Position(mapTemplateWorldX, mapTemplateWorldY, objectPosition.level), + ); + + const templateLocalX = getTemplateLocalX( + tileOrientation, + objectLocalX, + objectLocalY, + objectConfig?.rendering?.sizeX || 1, + objectConfig?.rendering?.sizeY || 1, + ); + const templateLocalY = getTemplateLocalY( + tileOrientation, + objectLocalX, + objectLocalY, + objectConfig?.rendering?.sizeX || 1, + objectConfig?.rendering?.sizeY || 1, + ); + + const templateObjectPosition = new Position( + mapTemplateWorldX + templateLocalX, + mapTemplateWorldY + templateLocalY, + objectPosition.level, + ); const realObject = mapTemplateChunk.getFilestoreLandscapeObject(objectId, templateObjectPosition); - if(!realObject) { + if (!realObject) { return null; } @@ -229,7 +249,7 @@ export class World { realObject.level = objectPosition.level; let rotation = realObject.orientation + objectTile.orientation; - if(rotation > 3) { + if (rotation > 3) { rotation -= 4; } @@ -243,15 +263,13 @@ export class World { * them out for a gentle game server shutdown. */ public kickAllPlayers(): void { - if(!this.playerList) { + if (!this.playerList) { return; } logger.info(`Kicking all players...`); - this.playerList - .filter(player => player !== null) - .forEach(player => player.logout()); + this.playerList.filter(player => player !== null).forEach(player => player.logout()); logger.info(`Player data save complete, world is now empty.`); } @@ -260,15 +278,13 @@ export class World { * Saves player data for every active player within the game world. */ public saveOnlinePlayers(): void { - if(!this.playerList) { + if (!this.playerList) { return; } logger.info(`Saving player data...`); - this.playerList - .filter(player => player !== null) - .forEach(player => player.save()); + this.playerList.filter(player => player !== null).forEach(player => player.save()); logger.info(`Player data saved.`); } @@ -283,12 +299,7 @@ export class World { public playLocationSound(position: Position, instanceId: string, soundId: number, volume: number, distance: number = 10): void { this.findNearbyPlayers(position, distance, instanceId).forEach(player => { player.outgoingPackets.updateReferencePosition(position); - player.outgoingPackets.playSoundAtPosition( - soundId, - position.x, - position.y, - volume - ); + player.outgoingPackets.playSoundAtPosition(soundId, position.x, position.y, volume); }); } @@ -299,13 +310,21 @@ export class World { * @param distance The maximum distance to search for NPCs. * @param instanceId The NPC's active instance. */ - public findNearbyNpcsById(position: Position, npcId: number, distance: number, instanceId: string = activeWorld.globalInstance.instanceId): Npc[] { - return this.npcTree.colliding({ - x: position.x - (distance / 2), - y: position.y - (distance / 2), - width: distance, - height: distance - }).map(quadree => quadree.actor as Npc).filter(npc => npc.id === npcId && npc.instanceId === instanceId); + public findNearbyNpcsById( + position: Position, + npcId: number, + distance: number, + instanceId: string = activeWorld.globalInstance.instanceId, + ): Npc[] { + return this.npcTree + .colliding({ + x: position.x - distance / 2, + y: position.y - distance / 2, + width: distance, + height: distance, + }) + .map(quadree => quadree.actor as Npc) + .filter(npc => npc.id === npcId && npc.instanceId === instanceId); } /** @@ -341,12 +360,15 @@ export class World { * @param instanceId The NPC's active instance. */ public findNearbyNpcs(position: Position, distance: number, instanceId: string = activeWorld.globalInstance.instanceId): Npc[] { - return this.npcTree.colliding({ - x: position.x - (distance / 2), - y: position.y - (distance / 2), - width: distance, - height: distance - }).map(quadree => quadree.actor as Npc).filter(npc => npc.instanceId === instanceId); + return this.npcTree + .colliding({ + x: position.x - distance / 2, + y: position.y - distance / 2, + width: distance, + height: distance, + }) + .map(quadree => quadree.actor as Npc) + .filter(npc => npc.instanceId === instanceId); } /** @@ -356,17 +378,15 @@ export class World { * @param instanceId The player's active instance. */ public findNearbyPlayers(position: Position, distance: number, instanceId: string): Player[] { - return this.playerTree.colliding({ - x: position.x - (distance / 2), - y: position.y - (distance / 2), - width: distance, - height: distance - }) + return this.playerTree + .colliding({ + x: position.x - distance / 2, + y: position.y - distance / 2, + width: distance, + height: distance, + }) .map(quadree => quadree.actor as Player) - .filter(player => ( - player.personalInstance.instanceId === instanceId - || player.instance?.instanceId === instanceId - )); + .filter(player => player.personalInstance.instanceId === instanceId || player.instance?.instanceId === instanceId); } /** @@ -385,12 +405,15 @@ export class World { public spawnWorldItems(player?: Player): void { const instance = player ? player.personalInstance : this.globalInstance; - itemSpawns.filter(spawn => player ? spawn.instance === 'player' : spawn.instance === 'global') + itemSpawns + .filter(spawn => (player ? spawn.instance === 'player' : spawn.instance === 'global')) .forEach(itemSpawn => { const itemDetails = findItem(itemSpawn.itemKey); - if(itemDetails && itemDetails.gameId !== undefined) { - instance.spawnWorldItem({ itemId: itemDetails.gameId, amount: itemSpawn.amount }, - itemSpawn.spawnPosition, { respawns: itemSpawn.respawn, owner: player || undefined }); + if (itemDetails && itemDetails.gameId !== undefined) { + instance.spawnWorldItem({ itemId: itemDetails.gameId, amount: itemSpawn.amount }, itemSpawn.spawnPosition, { + respawns: itemSpawn.respawn, + owner: player || undefined, + }); } else { logger.error(`Item ${itemSpawn.itemKey} can not be spawned; it has not yet been registered on the server.`); } @@ -404,16 +427,19 @@ export class World { }); } - public async spawnNpc(npcKey: string | number, position: Position, face: Direction, - movementRadius: number = 0, instanceId: string = activeWorld.globalInstance.instanceId): Promise { - if(!npcKey) { + public async spawnNpc( + npcKey: string | number, + position: Position, + face: Direction, + movementRadius: number = 0, + instanceId: string = activeWorld.globalInstance.instanceId, + ): Promise { + if (!npcKey) { throw new Error('NPC key must be provided.'); } const npcData = findNpc(npcKey); - const npc = new Npc(npcData, - new NpcSpawn(npcData.key ? npcData.key : `unknown_${npcData}` , - position, movementRadius, face)); + const npc = new Npc(npcData, new NpcSpawn(npcData.key ? npcData.key : `unknown_${npcData}`, position, movementRadius, face)); // TODO (jkm) this function doesn't use the passed in `instanceId`! @@ -423,8 +449,7 @@ export class World { } public spawnScenery(): void { - this.scenerySpawns.forEach(locationObject => - this.globalInstance.spawnGameObject(locationObject)); + this.scenerySpawns.forEach(locationObject => this.globalInstance.spawnGameObject(locationObject)); } public async setupWorldTick(): Promise { @@ -440,7 +465,7 @@ export class World { const spawnChunk = this.chunkManager.getChunkForWorldPosition(new Position(x, y, 0)); - for(let i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { // TODO (Jameskmonger) we should be able to create a player without a connection, and without passing nulls in const player = new Player(null as any, null as any, null as any, i, `test${i}`, 'abs', true); this.registerPlayer(player); @@ -448,7 +473,7 @@ export class World { xOffset++; - if(xOffset > 20) { + if (xOffset > 20) { xOffset = 0; yOffset--; } @@ -456,7 +481,7 @@ export class World { player.position = new Position(x + xOffset, y + yOffset, 0); const newChunk = this.chunkManager.getChunkForWorldPosition(player.position); - if(!spawnChunk.equals(newChunk)) { + if (!spawnChunk.equals(newChunk)) { spawnChunk.removePlayer(player); newChunk.addPlayer(player); } @@ -472,27 +497,27 @@ export class World { const activePlayers: Player[] = this.playerList.filter(player => player !== null); - if(activePlayers.length === 0) { + if (activePlayers.length === 0) { return Promise.resolve().then(() => { - setTimeout(async() => this.worldTick(), World.TICK_LENGTH); //TODO: subtract processing time + setTimeout(async () => this.worldTick(), World.TICK_LENGTH); //TODO: subtract processing time }); } const activeNpcs: Npc[] = this.npcList.filter(npc => npc !== null); - await Promise.all([ ...activePlayers.map(async player => player.tick()), ...activeNpcs.map(async npc => npc.tick()) ]); + await Promise.all([...activePlayers.map(async player => player.tick()), ...activeNpcs.map(async npc => npc.tick())]); await Promise.all(activePlayers.map(async player => player.update())); - await Promise.all([ ...activePlayers.map(async player => player.reset()), ...activeNpcs.map(async npc => npc.reset()) ]); + await Promise.all([...activePlayers.map(async player => player.reset()), ...activeNpcs.map(async npc => npc.reset())]); const hrEnd = Date.now(); const duration = hrEnd - hrStart; const delay = Math.max(World.TICK_LENGTH - duration, 0); - if(this.debugCycleDuration) { + if (this.debugCycleDuration) { logger.info(`World tick completed in ${duration} ms, next tick in ${delay} ms.`); } - setTimeout(async() => this.worldTick(), delay); + setTimeout(async () => this.worldTick(), delay); this.tickComplete.next(); return Promise.resolve(); } @@ -523,12 +548,12 @@ export class World { } public playerOnline(player: Player | string): boolean { - if(typeof player === 'string') { + if (typeof player === 'string') { player = player.toLowerCase(); return this.playerList.findIndex(p => Boolean(p) && p.username.toLowerCase() === player) !== -1; } else { const foundPlayer = this.playerList[player.worldIndex]; - if(!foundPlayer) { + if (!foundPlayer) { return false; } @@ -542,13 +567,13 @@ export class World { * @param player The player to register. */ public registerPlayer(player: Player): boolean { - if(!player) { + if (!player) { return false; } const index = this.playerList.findIndex(p => p === null); - if(index === -1) { + if (index === -1) { logger.warn('World full!'); return false; } @@ -568,7 +593,7 @@ export class World { public npcExists(npc: Npc): boolean { const foundNpc = this.npcList[npc.worldIndex]; - if(!foundNpc || !foundNpc.exists) { + if (!foundNpc || !foundNpc.exists) { return false; } @@ -576,13 +601,13 @@ export class World { } public async registerNpc(npc: Npc): Promise { - if(!npc) { + if (!npc) { return false; } const index = this.npcList.findIndex(n => n === null); - if(index === -1) { + if (index === -1) { logger.warn('NPC list full!'); return false; } @@ -597,5 +622,4 @@ export class World { npc.exists = false; delete this.npcList[npc.worldIndex]; } - } diff --git a/src/plugins/buttons/logout-button.plugin.ts b/src/plugins/buttons/logout-button.plugin.ts index a306b2f30..bde4a2d41 100644 --- a/src/plugins/buttons/logout-button.plugin.ts +++ b/src/plugins/buttons/logout-button.plugin.ts @@ -2,20 +2,18 @@ import type { buttonActionHandler } from '@engine/action/pipe/button.action'; import { widgets } from '@engine/config/config-handler'; import { activeWorld } from '@engine/world'; - -export const handler: buttonActionHandler = (details) => { +export const handler: buttonActionHandler = details => { const { player } = details; const playerName = player.username.toLowerCase(); player.logout(); // Update online players friends lists that have this player as a friend const otherPlayers = activeWorld.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); - if(otherPlayers && otherPlayers.length !== 0) { + if (otherPlayers && otherPlayers.length !== 0) { otherPlayers.forEach(otherPlayer => otherPlayer.outgoingPackets.updateFriendStatus(playerName, 0)); } }; - export default { pluginId: 'rs:logout_button', hooks: [ @@ -23,7 +21,7 @@ export default { type: 'button', widgetId: widgets.logoutTab, buttonIds: 6, - handler - } - ] + handler, + }, + ], }; diff --git a/src/plugins/buttons/magic-attack.plugin.ts b/src/plugins/buttons/magic-attack.plugin.ts index c6a137afc..1a284050d 100644 --- a/src/plugins/buttons/magic-attack.plugin.ts +++ b/src/plugins/buttons/magic-attack.plugin.ts @@ -12,21 +12,16 @@ function attack_target(player: Player, elapsedTicks: number): boolean { return true; } -const spells = ['Wind Strike','Confuse', 'Water Strike','unknown?', 'Earth Strike']; +const spells = ['Wind Strike', 'Confuse', 'Water Strike', 'unknown?', 'Earth Strike']; export const activate = (task: TaskExecutor, elapsedTicks: number = 0) => { - const { - npc, - player, - widgetId, - buttonId - } = task.actionData; + const { npc, player, widgetId, buttonId } = task.actionData; const attackerX = player.position.x; - const attackerY = player.position.y - const victimX = npc.position.x + const attackerY = player.position.y; + const victimX = npc.position.x; const victimY = npc.position.y; - const offsetX = ((victimY - attackerY)); - const offsetY = ((victimX - attackerX)); + const offsetX = victimY - attackerY; + const offsetY = victimX - attackerX; player.walkingQueue.clear(); @@ -37,14 +32,13 @@ export const activate = (task: TaskExecutor, elapsedTicks: num export default { pluginId: 'rs:magic', - hooks: - { - type: 'magic_on_npc', - widgetId: 192, - buttonIds: buttonIds, - task: { - activate, - interval: 0 - } - } as MagicOnNPCActionHook + hooks: { + type: 'magic_on_npc', + widgetId: 192, + buttonIds: buttonIds, + task: { + activate, + interval: 0, + }, + } as MagicOnNPCActionHook, }; diff --git a/src/plugins/buttons/magic-teleports.plugin.ts b/src/plugins/buttons/magic-teleports.plugin.ts index 689e29a5c..eb541831a 100644 --- a/src/plugins/buttons/magic-teleports.plugin.ts +++ b/src/plugins/buttons/magic-teleports.plugin.ts @@ -1,18 +1,18 @@ +import type { TaskExecutor } from '@engine/action/hook/task'; +import type { ButtonAction, ButtonActionHook } from '@engine/action/pipe/button.action'; +import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; +import { widgets } from '@engine/config/config-handler'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; +import { Skill } from '@engine/world/actor/skills'; import { animationIds } from '@engine/world/config/animation-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; import { gfxIds } from '@engine/world/config/gfx-ids'; import { itemIds } from '@engine/world/config/item-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; +import type { TravelLocation } from '@engine/world/config/travel-locations'; import type { Item } from '@engine/world/items/item'; -import { widgets } from '@engine/config/config-handler'; -import { activeWorld } from '@engine/world'; -import { Skill } from '@engine/world/actor/skills'; +import { Position } from '@engine/world/position'; import { openHouse } from '@plugins/skills/construction/house'; -import { QueueableTask } from '@engine/action/pipe/task/queueable-task'; -import type { TaskExecutor } from '@engine/action/hook/task'; -import type { ButtonAction, ButtonActionHook } from '@engine/action/pipe/button.action'; -import type { TravelLocation } from '@engine/world/config/travel-locations'; enum Teleports { Home = 591, @@ -24,7 +24,7 @@ enum Teleports { Ardougne = 388, Watchtower = 389, Trollheim = 492, - Ape_atoll = 569 + Ape_atoll = 569, } /** @@ -80,7 +80,7 @@ const MagicCosts: Record = { [itemIds.runes.water]: 2, [itemIds.banana]: 1, }, -} +}; /** * Mapping of the various teleport locations. Some are usable directly from @@ -96,7 +96,7 @@ const TeleportLocations: Record = { [Teleports.Watchtower]: new Position(2934, 4714, 2), [Teleports.Trollheim]: (activeWorld.travelLocations.find('Trollheim') as TravelLocation).position, [Teleports.Ape_atoll]: new Position(2798, 2798, 1), -} +}; const TeleportXP: Record = { [Teleports.Varrock]: 35, @@ -108,7 +108,7 @@ const TeleportXP: Record = { [Teleports.Watchtower]: 68, [Teleports.Trollheim]: 68, [Teleports.Ape_atoll]: 74, -} +}; const buttonIds: number[] = [ Teleports.Home, @@ -124,14 +124,22 @@ const buttonIds: number[] = [ ]; function queueTeleport(player: Player, pos: Position) { - player.enqueueBaseTask(new QueueableTask([], player, () => { - player.teleport(pos); - player.metadata.castingStationarySpell = false; - return { - callbackResult: false, - shouldContinueLooping: false, - } - }, null, null)) + player.enqueueBaseTask( + new QueueableTask( + [], + player, + () => { + player.teleport(pos); + player.metadata.castingStationarySpell = false; + return { + callbackResult: false, + shouldContinueLooping: false, + }; + }, + null, + null, + ), + ); } /** @@ -163,7 +171,7 @@ function homeTeleport(player: Player, elapsedTicks: number): boolean { player.playAnimation(animationIds.homeTeleport); player.playGraphics({ id: gfxIds.homeTeleport, delay: 0, height: 0 }); } else if (elapsedTicks === 22) { - queueTeleport(player, TeleportLocations[Teleports.Home]) + queueTeleport(player, TeleportLocations[Teleports.Home]); return true; } @@ -234,7 +242,7 @@ function expenseMagic(player: Player, cost: MagicCost): boolean { const newItem: Item = { amount: player.inventory.amount(itemId) - cost[requiredItemId], itemId: itemId, - } + }; if (newItem.amount < 0) { return false; @@ -246,7 +254,7 @@ function expenseMagic(player: Player, cost: MagicCost): boolean { for (let i = 0; i < indexesToUpdate.length; i++) { if (itemsToUpdate[indexesToUpdate[i]].amount === 0) { - player.inventory.remove(indexesToUpdate[i]) + player.inventory.remove(indexesToUpdate[i]); } else { player.inventory.set(indexesToUpdate[i], itemsToUpdate[indexesToUpdate[i]]); } @@ -257,7 +265,7 @@ function expenseMagic(player: Player, cost: MagicCost): boolean { function genericTeleport(player: Player, elapsedTicks: number, target: Position, teleportId?: number): boolean { if (elapsedTicks === 0) { - player.playAnimation(animationIds.teleport) + player.playAnimation(animationIds.teleport); player.outgoingPackets.playSound(soundIds.teleport, 10); player.playGraphics({ id: gfxIds.teleport, delay: 0, height: 100 }); } else if (elapsedTicks === 3) { @@ -267,20 +275,28 @@ function genericTeleport(player: Player, elapsedTicks: number, target: Position, break; } default: { - queueTeleport(player, target) + queueTeleport(player, target); // warning: undefined xp values cause the xp to reset to 0, // so make sure to always assert that it's defined if (teleportId && TeleportXP[teleportId]) { - player.enqueueBaseTask(new QueueableTask([], player, () => { - player.skills.addExp(Skill.MAGIC, TeleportXP[teleportId]) - return { callbackResult: false, shouldContinueLooping: false }; - }, null, null)); + player.enqueueBaseTask( + new QueueableTask( + [], + player, + () => { + player.skills.addExp(Skill.MAGIC, TeleportXP[teleportId]); + return { callbackResult: false, shouldContinueLooping: false }; + }, + null, + null, + ), + ); } break; } } - player.playAnimation(animationIds.reset) + player.playAnimation(animationIds.reset); return true; } @@ -347,8 +363,8 @@ export default { buttonIds: buttonIds, task: { activate, - interval: 1 - } - } as ButtonActionHook - ] + interval: 1, + }, + } as ButtonActionHook, + ], }; diff --git a/src/plugins/buttons/player-emotes.plugin.ts b/src/plugins/buttons/player-emotes.plugin.ts index 7baf6d597..3a2e2a060 100644 --- a/src/plugins/buttons/player-emotes.plugin.ts +++ b/src/plugins/buttons/player-emotes.plugin.ts @@ -1,7 +1,7 @@ +import type { buttonActionHandler } from '@engine/action/pipe/button.action'; +import { widgets } from '@engine/config/config-handler'; import type { Player } from '@engine/world/actor/player/player'; import { itemIds } from '@engine/world/config/item-ids'; -import { widgets } from '@engine/config/config-handler'; -import type { buttonActionHandler } from '@engine/action/pipe/button.action'; interface Emote { animationId: number; @@ -16,22 +16,37 @@ interface SkillcapeEmote extends Emote { const { skillCapes } = itemIds; -export const skillCapeEmotes: SkillcapeEmote[] = [ +export const skillCapeEmotes: SkillcapeEmote[] = [ { animationId: 4959, name: 'Attack', itemIds: [skillCapes.attack.untrimmed, skillCapes.attack.trimmed], graphicId: 823 }, { animationId: 4981, name: 'Strength', itemIds: [skillCapes.strength.untrimmed, skillCapes.strength.trimmed], graphicId: 828 }, { animationId: 4961, name: 'Defence', itemIds: [skillCapes.defence.untrimmed, skillCapes.defence.trimmed], graphicId: 824 }, { animationId: 4973, name: 'Ranged', itemIds: [skillCapes.ranged.untrimmed, skillCapes.ranged.trimmed], graphicId: 832 }, { animationId: 4979, name: 'Prayer', itemIds: [skillCapes.prayer.untrimmed, skillCapes.prayer.trimmed], graphicId: 829 }, { animationId: 4939, name: 'Magic', itemIds: [skillCapes.magic.untrimmed, skillCapes.magic.trimmed], graphicId: 813 }, - { animationId: 4947, name: 'Runecrafting', itemIds: [skillCapes.runecrafting.untrimmed, skillCapes.runecrafting.trimmed], graphicId: 817 }, - { animationId: 4971, name: 'Constitution', itemIds: [skillCapes.constitution.untrimmed, skillCapes.constitution.trimmed], graphicId: 833 }, + { + animationId: 4947, + name: 'Runecrafting', + itemIds: [skillCapes.runecrafting.untrimmed, skillCapes.runecrafting.trimmed], + graphicId: 817, + }, + { + animationId: 4971, + name: 'Constitution', + itemIds: [skillCapes.constitution.untrimmed, skillCapes.constitution.trimmed], + graphicId: 833, + }, { animationId: 4977, name: 'Agility', itemIds: [skillCapes.agility.untrimmed, skillCapes.agility.trimmed], graphicId: 830 }, { animationId: 4969, name: 'Herblore', itemIds: [skillCapes.herblore.untrimmed, skillCapes.herblore.trimmed], graphicId: 835 }, { animationId: 4965, name: 'Thieving', itemIds: [skillCapes.thieving.untrimmed, skillCapes.thieving.trimmed], graphicId: 826 }, { animationId: 4949, name: 'Crafting', itemIds: [skillCapes.crafting.untrimmed, skillCapes.crafting.trimmed], graphicId: 818 }, { animationId: 4937, name: 'Fletching', itemIds: [skillCapes.fletching.untrimmed, skillCapes.fletching.trimmed], graphicId: 812 }, { animationId: 4967, name: 'Slayer', itemIds: [skillCapes.slayer.untrimmed, skillCapes.slayer.trimmed], graphicId: 827 }, - { animationId: 4953, name: 'Construction', itemIds: [skillCapes.construction.untrimmed, skillCapes.construction.trimmed], graphicId: 820 }, + { + animationId: 4953, + name: 'Construction', + itemIds: [skillCapes.construction.untrimmed, skillCapes.construction.trimmed], + graphicId: 820, + }, { animationId: 4941, name: 'Mining', itemIds: [skillCapes.mining.untrimmed, skillCapes.mining.trimmed], graphicId: 814 }, { animationId: 4943, name: 'Smithing', itemIds: [skillCapes.smithing.untrimmed, skillCapes.smithing.trimmed], graphicId: 815 }, { animationId: 4951, name: 'Fishing', itemIds: [skillCapes.fishing.untrimmed, skillCapes.fishing.trimmed], graphicId: 819 }, @@ -43,27 +58,27 @@ export const skillCapeEmotes: SkillcapeEmote[] = [ ]; export const emotes: { [key: number]: Emote } = { - 1: { animationId: 855, name: 'YES' }, - 2: { animationId: 856, name: 'NO' }, - 3: { animationId: 858, name: 'BOW' }, - 4: { animationId: 859, name: 'ANGRY' }, - 5: { animationId: 857, name: 'THINKING' }, - 6: { animationId: 863, name: 'WAVE' }, - 7: { animationId: 2113, name: 'SHRUG' }, - 8: { animationId: 862, name: 'CHEER' }, - 9: { animationId: 864, name: 'BECKON' }, - 10: { animationId: 861, name: 'LAUGH' }, + 1: { animationId: 855, name: 'YES' }, + 2: { animationId: 856, name: 'NO' }, + 3: { animationId: 858, name: 'BOW' }, + 4: { animationId: 859, name: 'ANGRY' }, + 5: { animationId: 857, name: 'THINKING' }, + 6: { animationId: 863, name: 'WAVE' }, + 7: { animationId: 2113, name: 'SHRUG' }, + 8: { animationId: 862, name: 'CHEER' }, + 9: { animationId: 864, name: 'BECKON' }, + 10: { animationId: 861, name: 'LAUGH' }, 11: { animationId: 2109, name: 'JUMP FOR JOY' }, 12: { animationId: 2111, name: 'YAWN' }, - 13: { animationId: 866, name: 'DANCE' }, + 13: { animationId: 866, name: 'DANCE' }, 14: { animationId: 2106, name: 'JIG' }, 15: { animationId: 2107, name: 'SPIN' }, 16: { animationId: 2108, name: 'HEADBANG' }, - 17: { animationId: 860, name: 'CRY' }, + 17: { animationId: 860, name: 'CRY' }, 18: { animationId: 1368, name: 'BLOW KISS' }, 19: { animationId: 2105, name: 'PANIC' }, 20: { animationId: 2110, name: 'RASPBERRY' }, - 21: { animationId: 865, name: 'CLAP' }, + 21: { animationId: 865, name: 'CLAP' }, 22: { animationId: 2112, name: 'SALUTE' }, 23: { animationId: 2127, name: 'GOBLIN BOW', unlockable: true }, 24: { animationId: 2128, name: 'GOBLIN SALUTE', unlockable: true }, @@ -84,7 +99,7 @@ export const emotes: { [key: number]: Emote } = { export function unlockEmote(player: Player, emoteName: string): void { const unlockedEmotes: string[] = player.savedMetadata.unlockedEmotes || []; - if(unlockedEmotes.indexOf(emoteName) === -1) { + if (unlockedEmotes.indexOf(emoteName) === -1) { unlockedEmotes.push(emoteName); player.savedMetadata.unlockedEmotes = unlockedEmotes; } @@ -95,7 +110,7 @@ export function lockEmote(player: Player, emoteName: string): void { const unlockedEmotes: string[] = player.savedMetadata.unlockedEmotes || []; const index = unlockedEmotes.indexOf(emoteName); - if(index !== -1) { + if (index !== -1) { unlockedEmotes.splice(index, 1); player.savedMetadata.unlockedEmotes = unlockedEmotes; } @@ -110,35 +125,21 @@ export function unlockEmotes(player: Player): void { const unlockedEmotes: string[] = player.savedMetadata.unlockedEmotes || []; - for(const name of unlockedEmotes) { - if((name === 'GOBLIN BOW' || name === 'GOBLIN SALUTE') && goblinConfig === 0) - goblinConfig += 7; - if(name === 'FLAP') - sosConfig += 1; - if(name === 'FACEPALM') - sosConfig += 2; - if(name === 'IDEA') - sosConfig += 4; - if(name === 'STAMP') - sosConfig += 8; - if(name === 'GLASS WALL') - eventConfig += 1; - if(name === 'GLASS BOX') - eventConfig += 2; - if(name === 'CLIMB ROPE') - eventConfig += 4; - if(name === 'LEAN') - eventConfig += 8; - if(name === 'SCARED') - eventConfig += 16; - if(name === 'ZOMBIE DANCE') - eventConfig += 32; - if(name === 'ZOMBIE WALK') - eventConfig += 64; - if(name === 'RABBIT HOP') - eventConfig += 128; - if(name === 'SKILLCAPE') - eventConfig += 256; + for (const name of unlockedEmotes) { + if ((name === 'GOBLIN BOW' || name === 'GOBLIN SALUTE') && goblinConfig === 0) goblinConfig += 7; + if (name === 'FLAP') sosConfig += 1; + if (name === 'FACEPALM') sosConfig += 2; + if (name === 'IDEA') sosConfig += 4; + if (name === 'STAMP') sosConfig += 8; + if (name === 'GLASS WALL') eventConfig += 1; + if (name === 'GLASS BOX') eventConfig += 2; + if (name === 'CLIMB ROPE') eventConfig += 4; + if (name === 'LEAN') eventConfig += 8; + if (name === 'SCARED') eventConfig += 16; + if (name === 'ZOMBIE DANCE') eventConfig += 32; + if (name === 'ZOMBIE WALK') eventConfig += 64; + if (name === 'RABBIT HOP') eventConfig += 128; + if (name === 'SKILLCAPE') eventConfig += 256; } player.outgoingPackets.updateClientConfig(465, goblinConfig); @@ -148,13 +149,12 @@ export function unlockEmotes(player: Player): void { const buttonIds = Object.keys(emotes).map(v => parseInt(v)); - -export const handler: buttonActionHandler = (details) => { +export const handler: buttonActionHandler = details => { const { player, buttonId } = details; const emote = emotes[buttonId]; - if(emote.name === 'SKILLCAPE') { + if (emote.name === 'SKILLCAPE') { const equippedBackItem = player.getEquippedItem('back'); if (equippedBackItem) { @@ -166,14 +166,14 @@ export const handler: buttonActionHandler = (details) => { player.playGraphics({ id: skillcapeEmote[0].graphicId, delay: 0, height: 0 }); } } - } else { + } else { player.sendMessage(`You need to be wearing a skillcape in order to perform that emote.`, true); } } else { - if(emote.unlockable) { + if (emote.unlockable) { const unlockedEmotes: string[] = player.savedMetadata.unlockedEmotes || []; - if(unlockedEmotes.indexOf(emote.name) === -1) { + if (unlockedEmotes.indexOf(emote.name) === -1) { player.sendMessage(`You have not unlocked this emote.`, true); return; } @@ -181,16 +181,13 @@ export const handler: buttonActionHandler = (details) => { player.playAnimation(emote.animationId); - if(emote.graphicId !== undefined) { + if (emote.graphicId !== undefined) { player.playGraphics({ id: emote.graphicId, height: 0 }); } } }; - export default { pluginId: 'rs:player_emotes', - hooks: [ - { type: 'button', widgetId: widgets.emotesTab, buttonIds, handler } - ] + hooks: [{ type: 'button', widgetId: widgets.emotesTab, buttonIds, handler }], }; diff --git a/src/plugins/buttons/player-setting-button.plugin.ts b/src/plugins/buttons/player-setting-button.plugin.ts index 61accfbc2..8df1eaf86 100644 --- a/src/plugins/buttons/player-setting-button.plugin.ts +++ b/src/plugins/buttons/player-setting-button.plugin.ts @@ -3,25 +3,38 @@ import { widgets } from '@engine/config/config-handler'; const buttonIds: number[] = [ 0, // walk/run - 11, 12, 13, 14, 15, // music volume - 16, 17, 18, 19, 20, // sound effect volume - 29, 30, 31, 32, 33, // area effect volume + 11, + 12, + 13, + 14, + 15, // music volume + 16, + 17, + 18, + 19, + 20, // sound effect volume + 29, + 30, + 31, + 32, + 33, // area effect volume 2, // split private chat 3, // mouse buttons - 7, 8, 9, 10, // screen brightness + 7, + 8, + 9, + 10, // screen brightness 1, // chat effects 4, // accept aid 5, // house options ]; -export const handler: buttonActionHandler = (details) => { +export const handler: buttonActionHandler = details => { const { player, buttonId } = details; player.settingChanged(buttonId); }; export default { pluginId: 'rs:player_setting_button', - hooks: [ - { type: 'button', widgetId: widgets.settingsTab, buttonIds: buttonIds, handler } - ] + hooks: [{ type: 'button', widgetId: widgets.settingsTab, buttonIds: buttonIds, handler }], }; diff --git a/src/plugins/combat/combat-styles.plugin.ts b/src/plugins/combat/combat-styles.plugin.ts index 07f72f1ce..23a371115 100644 --- a/src/plugins/combat/combat-styles.plugin.ts +++ b/src/plugins/combat/combat-styles.plugin.ts @@ -1,22 +1,21 @@ -import type { equipmentChangeActionHandler, EquipmentChangeAction } from '@engine/action/pipe/equipment-change.action'; +import type { buttonActionHandler } from '@engine/action/pipe/button.action'; +import type { EquipmentChangeAction, equipmentChangeActionHandler } from '@engine/action/pipe/equipment-change.action'; +import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; +import { findItem, widgets } from '@engine/config/config-handler'; import type { ItemDetails, WeaponStyle } from '@engine/config/item-config'; import { weaponWidgetIds } from '@engine/config/item-config'; -import { widgetScripts } from '@engine/world/config/widget'; +import { combatStyles } from '@engine/world/actor/combat'; import type { Player } from '@engine/world/actor/player/player'; import { SidebarTab } from '@engine/world/actor/player/player'; -import { findItem, widgets } from '@engine/config/config-handler'; -import type { buttonActionHandler } from '@engine/action/pipe/button.action'; -import { combatStyles } from '@engine/world/actor/combat'; +import { widgetScripts } from '@engine/world/config/widget'; import { serverConfig } from '@server/game/game-server'; -import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; - export function updateCombatStyle(player: Player, weaponStyle: WeaponStyle, styleIndex: number): void { - player.savedMetadata.combatStyle = [ weaponStyle, styleIndex ]; + player.savedMetadata.combatStyle = [weaponStyle, styleIndex]; player.settings.attackStyle = styleIndex; const buttonId = combatStyles[weaponStyle]?.[styleIndex]?.button_id; - if(buttonId !== undefined) { + if (buttonId !== undefined) { player.outgoingPackets.updateClientConfig(widgetScripts.attackStyle, buttonId); } } @@ -25,9 +24,9 @@ export function showUnarmed(player: Player): void { player.modifyWidget(widgets.defaultCombatStyle, { childId: 0, text: 'Unarmed' }); player.setSidebarWidget(SidebarTab.COMBAT, widgets.defaultCombatStyle); let style = 0; - if(player.savedMetadata.combatStyle) { + if (player.savedMetadata.combatStyle) { style = player.savedMetadata.combatStyle[1] || null; - if(style && style > 2) { + if (style && style > 2) { style = 2; } } @@ -37,18 +36,18 @@ export function showUnarmed(player: Player): void { export function setWeaponWidget(player: Player, weaponStyle: WeaponStyle, itemDetails: ItemDetails | null): void { player.modifyWidget(weaponWidgetIds[weaponStyle], { childId: 0, text: itemDetails?.name || 'Unknown' }); player.setSidebarWidget(SidebarTab.COMBAT, weaponWidgetIds[weaponStyle]); - if(player.savedMetadata.combatStyle) { + if (player.savedMetadata.combatStyle) { updateCombatStyle(player, weaponStyle, player.savedMetadata.combatStyle[1] || 0); } } export function updateCombatStyleWidget(player: Player): void { const equippedItem = player.getEquippedItem('main_hand'); - if(equippedItem) { + if (equippedItem) { const itemDetails = findItem(equippedItem.itemId); const weaponStyle = itemDetails?.equipmentData?.weaponInfo?.style || null; - if(weaponStyle) { + if (weaponStyle) { setWeaponWidget(player, weaponStyle, itemDetails); } else { showUnarmed(player); @@ -59,10 +58,10 @@ export function updateCombatStyleWidget(player: Player): void { } const equip: equipmentChangeActionHandler = ({ player, itemDetails, equipmentSlot }) => { - if(equipmentSlot === 'main_hand') { + if (equipmentSlot === 'main_hand') { const weaponStyle = itemDetails?.equipmentData?.weaponInfo?.style || null; - if(!weaponStyle) { + if (!weaponStyle) { showUnarmed(player); return; } @@ -72,7 +71,7 @@ const equip: equipmentChangeActionHandler = ({ player, itemDetails, equipmentSlo }; const initAction: playerInitActionHandler = ({ player }) => { - if(!serverConfig.tutorialEnabled || player.savedMetadata.tutorialComplete) { + if (!serverConfig.tutorialEnabled || player.savedMetadata.tutorialComplete) { updateCombatStyleWidget(player); } }; @@ -81,39 +80,44 @@ const combatStyleSelection: buttonActionHandler = ({ player, buttonId }) => { const equippedItem = player.getEquippedItem('main_hand'); let weaponStyle: string | null = 'unarmed'; - if(equippedItem) { + if (equippedItem) { weaponStyle = findItem(equippedItem.itemId)?.equipmentData?.weaponInfo?.style || null; - if(!weaponStyle || !combatStyles[weaponStyle]) { + if (!weaponStyle || !combatStyles[weaponStyle]) { weaponStyle = 'unarmed'; } } const combatStyle = combatStyles[weaponStyle].findIndex(combatStyle => combatStyle.button_id === buttonId); - if(combatStyle !== -1) { - player.savedMetadata.combatStyle = [ weaponStyle, combatStyle ]; + if (combatStyle !== -1) { + player.savedMetadata.combatStyle = [weaponStyle, combatStyle]; } }; export default { pluginId: 'rs:combat_styles', - hooks: [{ - type: 'equipment_change', - eventType: 'equip', - handler: equip - }, { - type: 'equipment_change', - eventType: 'unequip', - handler: (details: EquipmentChangeAction): void => { - if(details.equipmentSlot === 'main_hand') { - showUnarmed(details.player); - } - } - }, { - type: 'player_init', - handler: initAction - }, { - type: 'button', - widgetIds: Object.values(weaponWidgetIds), - handler: combatStyleSelection - }] + hooks: [ + { + type: 'equipment_change', + eventType: 'equip', + handler: equip, + }, + { + type: 'equipment_change', + eventType: 'unequip', + handler: (details: EquipmentChangeAction): void => { + if (details.equipmentSlot === 'main_hand') { + showUnarmed(details.player); + } + }, + }, + { + type: 'player_init', + handler: initAction, + }, + { + type: 'button', + widgetIds: Object.values(weaponWidgetIds), + handler: combatStyleSelection, + }, + ], }; diff --git a/src/plugins/commands/bank-command.plugin.ts b/src/plugins/commands/bank-command.plugin.ts index f42f34a63..27eb9311c 100644 --- a/src/plugins/commands/bank-command.plugin.ts +++ b/src/plugins/commands/bank-command.plugin.ts @@ -4,9 +4,10 @@ import type { ObjectInteractionActionHook } from '@engine/action/pipe/object-int import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { objectIds } from '@engine/world/config/object-ids'; -const action: commandActionHandler = (details) => { - const interactionActions = getActionHooks('object_interaction') - .filter(plugin => advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly')); +const action: commandActionHandler = details => { + const interactionActions = getActionHooks('object_interaction').filter(plugin => + advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly'), + ); interactionActions.forEach(plugin => { if (!plugin.handler) { return; @@ -20,13 +21,13 @@ const action: commandActionHandler = (details) => { x: details.player.position.x, y: details.player.position.y, orientation: 0, - type: 0 + type: 0, }, option: 'use-quickly', position: details.player.position, objectConfig: undefined as any, - cacheOriginal: undefined as any - }) + cacheOriginal: undefined as any, + }); }); }; @@ -35,8 +36,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'bank' ], - handler: action - } - ] + commands: ['bank'], + handler: action, + }, + ], }; diff --git a/src/plugins/commands/camera-commands.plugin.ts b/src/plugins/commands/camera-commands.plugin.ts index d3d49907d..207f9166a 100644 --- a/src/plugins/commands/camera-commands.plugin.ts +++ b/src/plugins/commands/camera-commands.plugin.ts @@ -1,25 +1,40 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { Position } from '@engine/world/position'; - const moveCameraAction: commandActionHandler = ({ player, args }) => { const { x, y, height, speed, acceleration } = args; - player.outgoingPackets.snapCameraTo(new Position(x as number, y as number, player.position.level), - height as number, speed as number, acceleration as number); + player.outgoingPackets.snapCameraTo( + new Position(x as number, y as number, player.position.level), + height as number, + speed as number, + acceleration as number, + ); }; const turnCameraAction: commandActionHandler = ({ player, args }) => { const { x, y, height, speed, acceleration } = args; - player.outgoingPackets.turnCameraTowards(new Position(x as number, y as number, player.position.level), - height as number, speed as number, acceleration as number); + player.outgoingPackets.turnCameraTowards( + new Position(x as number, y as number, player.position.level), + height as number, + speed as number, + acceleration as number, + ); }; const lookCameraAction: commandActionHandler = ({ player, args }) => { const { cameraX, cameraY, cameraHeight, lookX, lookY, lookHeight, speed, acceleration } = args; - player.outgoingPackets.snapCameraTo(new Position(cameraX as number, cameraY as number, player.position.level), - cameraHeight as number, speed as number, acceleration as number); - player.outgoingPackets.turnCameraTowards(new Position(lookX as number, lookY as number, player.position.level), - lookHeight as number, speed as number, acceleration as number); + player.outgoingPackets.snapCameraTo( + new Position(cameraX as number, cameraY as number, player.position.level), + cameraHeight as number, + speed as number, + acceleration as number, + ); + player.outgoingPackets.turnCameraTowards( + new Position(lookX as number, lookY as number, player.position.level), + lookHeight as number, + speed as number, + acceleration as number, + ); }; const lookTestAction: commandActionHandler = ({ player }) => { @@ -41,104 +56,107 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'looktest', 'lt' ], - handler: lookTestAction - }, { + commands: ['looktest', 'lt'], + handler: lookTestAction, + }, + { type: 'player_command', - commands: [ 'cameralook' ], + commands: ['cameralook'], args: [ { name: 'cameraX', - type: 'number' + type: 'number', }, { name: 'cameraY', - type: 'number' + type: 'number', }, { name: 'cameraHeight', - type: 'number' + type: 'number', }, { name: 'lookX', - type: 'number' + type: 'number', }, { name: 'lookY', - type: 'number' + type: 'number', }, { name: 'lookHeight', - type: 'number' + type: 'number', }, { name: 'speed', type: 'number', - defaultValue: 0 + defaultValue: 0, }, { name: 'acceleration', type: 'number', - defaultValue: 100 - } + defaultValue: 100, + }, ], - handler: lookCameraAction - }, { + handler: lookCameraAction, + }, + { type: 'player_command', - commands: [ 'mcam', 'movecamera', 'move_camera', 'setcam', 'setcamera', 'set_camera' ], + commands: ['mcam', 'movecamera', 'move_camera', 'setcam', 'setcamera', 'set_camera'], args: [ { name: 'x', - type: 'number' + type: 'number', }, { name: 'y', - type: 'number' + type: 'number', }, { name: 'height', - type: 'number' + type: 'number', }, { name: 'speed', type: 'number', - defaultValue: 0 + defaultValue: 0, }, { name: 'acceleration', type: 'number', - defaultValue: 100 - } + defaultValue: 100, + }, ], - handler: moveCameraAction - }, { + handler: moveCameraAction, + }, + { type: 'player_command', - commands: [ 'tcam', 'turncamera', 'turn_camera' ], + commands: ['tcam', 'turncamera', 'turn_camera'], args: [ { name: 'x', - type: 'number' + type: 'number', }, { name: 'y', - type: 'number' + type: 'number', }, { name: 'height', - type: 'number' + type: 'number', }, { name: 'speed', type: 'number', - defaultValue: 0 + defaultValue: 0, }, { name: 'acceleration', type: 'number', - defaultValue: 100 - } + defaultValue: 100, + }, ], - handler: turnCameraAction - } - ] + handler: turnCameraAction, + }, + ], }; diff --git a/src/plugins/commands/clear-inventory-command.plugin.ts b/src/plugins/commands/clear-inventory-command.plugin.ts index 672c4c2a3..213ecb1e1 100644 --- a/src/plugins/commands/clear-inventory-command.plugin.ts +++ b/src/plugins/commands/clear-inventory-command.plugin.ts @@ -2,10 +2,11 @@ import type { PlayerCommandAction } from '@engine/action/pipe/player-command.act export default { pluginId: 'rs:clear_inventory_command', - hooks: [ { - type: 'player_command', - commands: [ 'clear' ], - handler: (details: PlayerCommandAction): void => details.player.inventory.clear() - } - ] + hooks: [ + { + type: 'player_command', + commands: ['clear'], + handler: (details: PlayerCommandAction): void => details.player.inventory.clear(), + }, + ], }; diff --git a/src/plugins/commands/client-config-command.plugin.ts b/src/plugins/commands/client-config-command.plugin.ts index 541b101c6..b8bb881a5 100644 --- a/src/plugins/commands/client-config-command.plugin.ts +++ b/src/plugins/commands/client-config-command.plugin.ts @@ -1,6 +1,6 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const configId = args.configId as number; @@ -14,18 +14,18 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'config', 'conf' ], + commands: ['config', 'conf'], args: [ { name: 'configId', - type: 'number' + type: 'number', }, { name: 'configValue', - type: 'number' - } + type: 'number', + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/current-position-command.plugin.ts b/src/plugins/commands/current-position-command.plugin.ts index 20f4cc585..2e7cb886c 100644 --- a/src/plugins/commands/current-position-command.plugin.ts +++ b/src/plugins/commands/current-position-command.plugin.ts @@ -1,6 +1,6 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player } = details; player.sendLogMessage(`@[ ${player.position.x}, ${player.position.y}, ${player.position.level} ]`, details.isConsole); }; @@ -10,8 +10,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'pos', 'loc', 'position', 'location', 'coords', 'coordinates', 'mypos', 'myloc' ], - handler: action - } - ] + commands: ['pos', 'loc', 'position', 'location', 'coords', 'coordinates', 'mypos', 'myloc'], + handler: action, + }, + ], }; diff --git a/src/plugins/commands/data-dump-command.plugin.ts b/src/plugins/commands/data-dump-command.plugin.ts index f659a8419..f6a21999a 100644 --- a/src/plugins/commands/data-dump-command.plugin.ts +++ b/src/plugins/commands/data-dump-command.plugin.ts @@ -2,34 +2,33 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.ac import type { DataDumpResult } from '@engine/config/data-dump'; import { dumpItems, dumpNpcs, dumpObjects, dumpWidgets } from '@engine/config/data-dump'; - const action: commandActionHandler = ({ player, args, isConsole }) => { const dataType = args.dataType as string; const functionMap: { [key: string]: () => DataDumpResult } = { - 'npcs': dumpNpcs, - 'items': dumpItems, - 'objects': dumpObjects, - 'widgets': dumpWidgets, + npcs: dumpNpcs, + items: dumpItems, + objects: dumpObjects, + widgets: dumpWidgets, }; const types = Object.keys(functionMap); - if(types.indexOf(dataType) === -1) { + if (types.indexOf(dataType) === -1) { player.sendLogMessage(`Invalid data type, please use one of the following:`, isConsole); player.sendLogMessage(`[ ${types.join(', ')} ]`, isConsole); return; } let dataName = dataType; - if(dataType.endsWith('s')) { + if (dataType.endsWith('s')) { dataName = dataType.substring(0, dataType.length - 2); } player.sendLogMessage(`Dumping ${dataName} data...`, isConsole); const result = functionMap[dataType](); - if(result.successful) { + if (result.successful) { player.sendLogMessage(`Saved ${dataName} data to ${result.filePath}.`, isConsole); } else { player.sendLogMessage(`Error dumping ${dataName} data.`, isConsole); @@ -41,14 +40,14 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'dump', 'data', 'datadump', 'dd' ], + commands: ['dump', 'data', 'datadump', 'dd'], args: [ { name: 'dataType', - type: 'string' - } + type: 'string', + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/dump-metadata-command.plugin.ts b/src/plugins/commands/dump-metadata-command.plugin.ts index 0b1f297d3..5282f2acf 100644 --- a/src/plugins/commands/dump-metadata-command.plugin.ts +++ b/src/plugins/commands/dump-metadata-command.plugin.ts @@ -1,25 +1,29 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player } = details; const metadata = { ...player.metadata }; for (const metadataKey of Object.keys(metadata)) { - if(typeof (metadata as any)[metadataKey] === 'function') { + if (typeof (metadata as any)[metadataKey] === 'function') { (metadata as any)[metadataKey] = typeof (metadata as any)[metadataKey]; } - if(Array.isArray((metadata as any)[metadataKey]) && (metadata as any)[metadataKey].length > 30) { + if (Array.isArray((metadata as any)[metadataKey]) && (metadata as any)[metadataKey].length > 30) { (metadata as any)[metadataKey] = `Array (${(metadata as any)[metadataKey].length} entries)`; } - if(typeof (metadata as any)[metadataKey] === 'object'&&(metadata as any)[metadataKey] !== null && 'unsubscribe' in (metadata as any)[metadataKey]) { + if ( + typeof (metadata as any)[metadataKey] === 'object' && + (metadata as any)[metadataKey] !== null && + 'unsubscribe' in (metadata as any)[metadataKey] + ) { (metadata as any)[metadataKey] = `Observable { closed: ${(metadata as any)[metadataKey].closed} }`; } } console.log(metadata); const stringified = JSON.stringify(metadata, null, 4); - stringified.split('\n').forEach((split) => { + stringified.split('\n').forEach(split => { player.sendLogMessage(split, details.isConsole); console.log(split); - }) + }); }; export default { @@ -27,8 +31,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'dump_metadata' ], - handler: action - } - ] + commands: ['dump_metadata'], + handler: action, + }, + ], }; diff --git a/src/plugins/commands/give-item-command.plugin.ts b/src/plugins/commands/give-item-command.plugin.ts index 79e0b5373..c931f13d8 100644 --- a/src/plugins/commands/give-item-command.plugin.ts +++ b/src/plugins/commands/give-item-command.plugin.ts @@ -1,13 +1,13 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -import { itemIds } from '@engine/world/config/item-ids'; import { findItem } from '@engine/config/config-handler'; +import { itemIds } from '@engine/world/config/item-ids'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const inventorySlot = player.inventory.getFirstOpenSlot(); - if(inventorySlot === -1) { + if (inventorySlot === -1) { player.sendLogMessage(`You don't have enough free space to do that.`, details.isConsole); return; } @@ -15,10 +15,10 @@ const action: commandActionHandler = (details) => { const itemSearch: string = args.itemSearch as string; let itemId: number | null = null; - if(itemSearch.match(/^[0-9]+$/)) { + if (itemSearch.match(/^[0-9]+$/)) { itemId = parseInt(itemSearch, 10); } else { - if(itemSearch.indexOf(':') !== -1) { + if (itemSearch.indexOf(':') !== -1) { itemId = findItem(itemSearch)?.gameId || null; } else { // @TODO nested item ids @@ -26,33 +26,33 @@ const action: commandActionHandler = (details) => { } } - if(!itemId || isNaN(itemId)) { + if (!itemId || isNaN(itemId)) { throw new Error(`Item name not found.`); } let amount: number = args.amount as number; - if(amount > 2000000000) { + if (amount > 2000000000) { throw new Error(`Unable to give more than 2,000,000,000.`); } const itemDefinition = findItem(itemId); - if(!itemDefinition) { + if (!itemDefinition) { throw new Error(`Item ID ${itemId} not found!`); } let actualAmount = 0; - if(itemDefinition.stackable) { + if (itemDefinition.stackable) { const item = { itemId, amount }; player.giveItem(item); actualAmount = amount; } else { - if(amount > 28) { + if (amount > 28) { amount = 28; } - for(let i = 0; i < amount; i++) { - if(player.giveItem({ itemId, amount: 1 })) { + for (let i = 0; i < amount; i++) { + if (player.giveItem({ itemId, amount: 1 })) { actualAmount++; } else { break; @@ -61,7 +61,6 @@ const action: commandActionHandler = (details) => { } player.sendLogMessage(`Added ${actualAmount}x ${itemDefinition.name} to inventory.`, details.isConsole); - }; export default { @@ -69,19 +68,19 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'give', 'item', 'spawn' ], + commands: ['give', 'item', 'spawn'], args: [ { name: 'itemSearch', - type: 'string' + type: 'string', }, { name: 'amount', type: 'number', - defaultValue: 1 - } + defaultValue: 1, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/groups-debug.plugin.ts b/src/plugins/commands/groups-debug.plugin.ts index 49bf68e6e..4acdd19e7 100644 --- a/src/plugins/commands/groups-debug.plugin.ts +++ b/src/plugins/commands/groups-debug.plugin.ts @@ -1,14 +1,14 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -import { findItemTagsInGroups, findItemTagsInGroupFilter } from '@engine/config/config-handler'; +import { findItemTagsInGroupFilter, findItemTagsInGroups } from '@engine/config/config-handler'; const selectGroups: commandActionHandler = ({ player, args, isConsole }) => { const groups: string | number = args.groupkeys; - if(!groups || typeof groups !== 'string') { + if (!groups || typeof groups !== 'string') { player.sendLogMessage('invalid input', isConsole); return; } player.sendLogMessage('results:', isConsole); - findItemTagsInGroups(groups.split(',')).forEach((itemName) => { + findItemTagsInGroups(groups.split(',')).forEach(itemName => { player.sendLogMessage(itemName, isConsole); }); return; @@ -16,13 +16,13 @@ const selectGroups: commandActionHandler = ({ player, args, isConsole }) => { const filterGroups: commandActionHandler = ({ player, args, isConsole }) => { const groups: string | number = args.groupkeys; - if(!groups || typeof groups !== 'string') { + if (!groups || typeof groups !== 'string') { player.sendLogMessage('invalid input', isConsole); return; } player.sendLogMessage('results:', isConsole); - findItemTagsInGroupFilter(groups.split(',')).forEach((itemName) => { + findItemTagsInGroupFilter(groups.split(',')).forEach(itemName => { player.sendLogMessage(itemName, isConsole); }); return; @@ -33,25 +33,25 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'selectgroups' ], + commands: ['selectgroups'], args: [ { name: 'groupkeys', - type: 'string' - } + type: 'string', + }, ], - handler: selectGroups + handler: selectGroups, }, { type: 'player_command', - commands: [ 'filtergroups' ], + commands: ['filtergroups'], args: [ { name: 'groupkeys', - type: 'string' - } + type: 'string', + }, ], - handler: filterGroups - } - ] + handler: filterGroups, + }, + ], }; diff --git a/src/plugins/commands/pathing-commands.plugin.ts b/src/plugins/commands/pathing-commands.plugin.ts index 986c443fd..326291a2e 100644 --- a/src/plugins/commands/pathing-commands.plugin.ts +++ b/src/plugins/commands/pathing-commands.plugin.ts @@ -1,7 +1,7 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { Position } from '@engine/world/position'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const x: number = args.x as number; @@ -16,23 +16,23 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'path' ], + commands: ['path'], args: [ { name: 'x', - type: 'number' + type: 'number', }, { name: 'y', - type: 'number' + type: 'number', }, { name: 'diameter', type: 'number', - defaultValue: 64 - } + defaultValue: 64, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/player-animation-command.plugin.ts b/src/plugins/commands/player-animation-command.plugin.ts index 496180317..8f6f215b8 100644 --- a/src/plugins/commands/player-animation-command.plugin.ts +++ b/src/plugins/commands/player-animation-command.plugin.ts @@ -1,4 +1,4 @@ -import type { commandActionHandler, PlayerCommandActionHook } from '@engine/action/pipe/player-command.action'; +import type { PlayerCommandActionHook, commandActionHandler } from '@engine/action/pipe/player-command.action'; const action: commandActionHandler = (details): void => { const { player, args } = details; @@ -12,14 +12,14 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'anim', 'animation', 'playanim' ], + commands: ['anim', 'animation', 'playanim'], args: [ { name: 'animationId', - type: 'number' - } + type: 'number', + }, ], - handler: action - } as PlayerCommandActionHook - ] + handler: action, + } as PlayerCommandActionHook, + ], }; diff --git a/src/plugins/commands/player-graphics-command.plugin.ts b/src/plugins/commands/player-graphics-command.plugin.ts index b230885dd..05d33b93d 100644 --- a/src/plugins/commands/player-graphics-command.plugin.ts +++ b/src/plugins/commands/player-graphics-command.plugin.ts @@ -1,6 +1,6 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const graphicsId: number = args.graphicsId as number; @@ -14,19 +14,19 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'gfx', 'graphics' ], + commands: ['gfx', 'graphics'], args: [ { name: 'graphicsId', - type: 'number' + type: 'number', }, { name: 'height', type: 'number', - defaultValue: 120 - } + defaultValue: 120, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/quest-list-command.plugin.ts b/src/plugins/commands/quest-list-command.plugin.ts index 88b16f2bf..2fad534f1 100644 --- a/src/plugins/commands/quest-list-command.plugin.ts +++ b/src/plugins/commands/quest-list-command.plugin.ts @@ -1,7 +1,7 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { questMap } from '@engine/plugins/loader'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { for (const quest of Object.values(questMap)) { details.player.sendLogMessage(quest.id, details.isConsole); } @@ -12,8 +12,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'quest-list', 'quests' ], - handler: action - } - ] + commands: ['quest-list', 'quests'], + handler: action, + }, + ], }; diff --git a/src/plugins/commands/region-debug-commands.plugin.ts b/src/plugins/commands/region-debug-commands.plugin.ts index c46430dd1..1802257f9 100644 --- a/src/plugins/commands/region-debug-commands.plugin.ts +++ b/src/plugins/commands/region-debug-commands.plugin.ts @@ -1,22 +1,26 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; -import { logger } from '@runejs/common'; import { Position } from '@engine/world/position'; -import { activeWorld } from '@engine/world'; - - +import { logger } from '@runejs/common'; -const debugMapRegion = (player: Player, mapRegionX: number, mapRegionY: number, - worldX: number, worldY: number, level: number = -1): void => { +const debugMapRegion = ( + player: Player, + mapRegionX: number, + mapRegionY: number, + worldX: number, + worldY: number, + level: number = -1, +): void => { const key = `${mapRegionX},${mapRegionY}`; player.sendMessage(`Region ${key} - ${activeWorld.chunkManager.getRegionIdForWorldPosition(player.position)}`); - if(!activeWorld.chunkManager.regionMap.has(key)) { + if (!activeWorld.chunkManager.regionMap.has(key)) { player.sendMessage(`Map region not loaded.`); return; } - if(level === -1) { + if (level === -1) { level = player.position.level; } @@ -24,25 +28,24 @@ const debugMapRegion = (player: Player, mapRegionX: number, mapRegionY: number, if (!region) { player.sendMessage(`Map region not loaded.`); - logger.error(`Map region not loaded. ${key}`) + logger.error(`Map region not loaded. ${key}`); return; } let debug: string = `\nRegion ${key},${level}\n\n`; - for(let y = 63; y >= 0; y--) { + for (let y = 63; y >= 0; y--) { const line = new Array(64).fill('?'); - for(let x = 0; x < 64; x++) { + for (let x = 0; x < 64; x++) { const tileWorldX = worldX + x; const tileWorldY = worldY + y; - if(tileWorldX === player.position.x && tileWorldY === player.position.y) { + if (tileWorldX === player.position.x && tileWorldY === player.position.y) { line[x] = '@'; - } else if(region.mapFile?.tileSettings) { - const tileSettings = activeWorld.chunkManager - .getTile(new Position(tileWorldX, tileWorldY, level)).settings; + } else if (region.mapFile?.tileSettings) { + const tileSettings = activeWorld.chunkManager.getTile(new Position(tileWorldX, tileWorldY, level)).settings; - if(!tileSettings) { + if (!tileSettings) { line[x] = '.'; - } else if(tileSettings > 9) { + } else if (tileSettings > 9) { line[x] = 'x'; } else { line[x] = tileSettings + ''; @@ -63,7 +66,7 @@ const regionDebugHandler: commandActionHandler = ({ player, args }) => { const worldX = (mapRegionX & 0xff) * 64; const worldY = mapRegionY * 64; - debugMapRegion(player, mapRegionX, mapRegionY, worldX, worldY, args?.level as number || -1); + debugMapRegion(player, mapRegionX, mapRegionY, worldX, worldY, (args?.level as number) || -1); }; const tileDebugHandler: commandActionHandler = ({ player }) => { @@ -81,11 +84,14 @@ const tileDebugHandler: commandActionHandler = ({ player }) => { const worldX = (mapRegionX & 0xff) * 64; const worldY = mapRegionY * 64; - player.sendMessage([ - `Tile ${player.position.key} settings: ${tile.settings}`, - `Local Pos: ${player.position.x - worldX},${player.position.y - worldY}`, - `Tile@0=(${tile0.settings}), Tile@1=(${tile1.settings}), Tile@2=(${tile2.settings}), Tile@3=(${tile3.settings})` - ], { console: true }); + player.sendMessage( + [ + `Tile ${player.position.key} settings: ${tile.settings}`, + `Local Pos: ${player.position.x - worldX},${player.position.y - worldY}`, + `Tile@0=(${tile0.settings}), Tile@1=(${tile1.settings}), Tile@2=(${tile2.settings}), Tile@3=(${tile3.settings})`, + ], + { console: true }, + ); }; export default { @@ -93,24 +99,20 @@ export default { hooks: [ { type: 'player_command', - commands: [ - 'regioninfo', 'region', 'myregion', 'regiondebug', 'region_info', 'my_region', 'region_debug' - ], + commands: ['regioninfo', 'region', 'myregion', 'regiondebug', 'region_info', 'my_region', 'region_debug'], args: [ { name: 'level', type: 'number', - defaultValue: -1 - } + defaultValue: -1, + }, ], - handler: regionDebugHandler + handler: regionDebugHandler, }, { type: 'player_command', - commands: [ - 'tileinfo', 'tile', 'mytile', 'tiledebug', 'tile_info', 'my_tile', 'tile_debug' - ], - handler: tileDebugHandler - } - ] + commands: ['tileinfo', 'tile', 'mytile', 'tiledebug', 'tile_info', 'my_tile', 'tile_debug'], + handler: tileDebugHandler, + }, + ], }; diff --git a/src/plugins/commands/reset-camera-command.plugin.ts b/src/plugins/commands/reset-camera-command.plugin.ts index c13cb1150..67ca6f19f 100644 --- a/src/plugins/commands/reset-camera-command.plugin.ts +++ b/src/plugins/commands/reset-camera-command.plugin.ts @@ -5,8 +5,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'reset_camera', 'resetcamera' ], - handler: ({ player }: PlayerCommandAction): void => player.outgoingPackets.resetCamera() - } - ] + commands: ['reset_camera', 'resetcamera'], + handler: ({ player }: PlayerCommandAction): void => player.outgoingPackets.resetCamera(), + }, + ], }; diff --git a/src/plugins/commands/sound-song-commands.plugin.ts b/src/plugins/commands/sound-song-commands.plugin.ts index 4a2a8ffe3..37b762e6c 100644 --- a/src/plugins/commands/sound-song-commands.plugin.ts +++ b/src/plugins/commands/sound-song-commands.plugin.ts @@ -1,16 +1,16 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const songAction: commandActionHandler = (details) => { +const songAction: commandActionHandler = details => { const { player, args } = details; player.outgoingPackets.playSong(args.songId as number); }; -const soundAction: commandActionHandler = (details) => { +const soundAction: commandActionHandler = details => { const { player, args } = details; player.playSound(args.soundId as number, args.volume as number); }; -const quickSongAction: commandActionHandler = (details) => { +const quickSongAction: commandActionHandler = details => { const { player, args } = details; player.outgoingPackets.playQuickSong(args.songId as number, args.prevSongId as number); }; @@ -24,39 +24,41 @@ export default { args: [ { name: 'songId', - type: 'number' - } + type: 'number', + }, ], - handler: songAction - }, { + handler: songAction, + }, + { type: 'player_command', - commands: [ 'sound', 'so' ], + commands: ['sound', 'so'], args: [ { name: 'soundId', - type: 'number' + type: 'number', }, { name: 'volume', type: 'number', - defaultValue: 10 - } + defaultValue: 10, + }, ], - handler: soundAction - }, { + handler: soundAction, + }, + { type: 'player_command', commands: 'quicksong', args: [ { name: 'songId', - type: 'number' + type: 'number', }, { name: 'prevSongId', - type: 'number' - } + type: 'number', + }, ], - handler: quickSongAction - } - ] + handler: quickSongAction, + }, + ], }; diff --git a/src/plugins/commands/spawn-npc-command.plugin.ts b/src/plugins/commands/spawn-npc-command.plugin.ts index 79d6168d8..1e834b689 100644 --- a/src/plugins/commands/spawn-npc-command.plugin.ts +++ b/src/plugins/commands/spawn-npc-command.plugin.ts @@ -1,28 +1,30 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -import { Npc } from '@engine/world/actor/npc'; import { findNpc } from '@engine/config/config-handler'; import type { NpcDetails } from '@engine/config/npc-config'; import { NpcSpawn } from '@engine/config/npc-spawn-config'; import { activeWorld } from '@engine/world'; +import { Npc } from '@engine/world/actor/npc'; const action: commandActionHandler = ({ player, args }) => { let npcKey: string | number = args.npcKey; let npcDetails: NpcDetails | null = null; - if(typeof npcKey === 'string' && npcKey.match(/^[0-9]+$/)) { + if (typeof npcKey === 'string' && npcKey.match(/^[0-9]+$/)) { npcKey = parseInt(npcKey, 10); } - if(typeof npcKey === 'string') { + if (typeof npcKey === 'string') { npcDetails = findNpc(npcKey); npcKey = npcDetails.gameId; } const movementRadius: number = args.movementRadius as number; - const npc = new Npc(npcDetails ? npcDetails : npcKey, - new NpcSpawn(npcDetails?.key ? npcDetails.key : `unknown-${npcKey}`, - player.position.clone(), movementRadius, 'WEST'), player.instance); + const npc = new Npc( + npcDetails ? npcDetails : npcKey, + new NpcSpawn(npcDetails?.key ? npcDetails.key : `unknown-${npcKey}`, player.position.clone(), movementRadius, 'WEST'), + player.instance, + ); activeWorld.registerNpc(npc); }; @@ -32,19 +34,19 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'npc', 'spawnnpc', 'spawn_npc' ], + commands: ['npc', 'spawnnpc', 'spawn_npc'], args: [ { name: 'npcKey', - type: 'either' + type: 'either', }, { name: 'movementRadius', type: 'number', - defaultValue: 0 - } + defaultValue: 0, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/spawn-scenery-command.plugin.ts b/src/plugins/commands/spawn-scenery-command.plugin.ts index d7129aee4..f6cd565f7 100644 --- a/src/plugins/commands/spawn-scenery-command.plugin.ts +++ b/src/plugins/commands/spawn-scenery-command.plugin.ts @@ -1,22 +1,22 @@ +import { writeFileSync } from 'fs'; import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { objectIds } from '@engine/world/config/object-ids'; -import { dump } from 'js-yaml'; -import { writeFileSync } from 'fs'; import { logger } from '@runejs/common'; import type { LandscapeObject } from '@runejs/filestore'; +import { dump } from 'js-yaml'; const spawnSceneryAction: commandActionHandler = ({ player, args }) => { const locationObjectSearch: string = (args.locationObjectSearch as string).trim(); let locationObjectId: number; - if(locationObjectSearch.match(/^[0-9]+$/)) { + if (locationObjectSearch.match(/^[0-9]+$/)) { locationObjectId = parseInt(locationObjectSearch, 10); } else { // @TODO nested object ids locationObjectId = objectIds[locationObjectSearch]; } - if(isNaN(locationObjectId)) { + if (isNaN(locationObjectId)) { throw new Error(`Location object name not found.`); } @@ -31,12 +31,12 @@ const spawnSceneryAction: commandActionHandler = ({ player, args }) => { y: position.y, level: position.level, type: objectType, - orientation: objectOrientation + orientation: objectOrientation, }; player.metadata.lastSpawnedScenery = locationObject; - if(!player.metadata.spawnedScenery) { + if (!player.metadata.spawnedScenery) { player.metadata.spawnedScenery = []; } @@ -45,27 +45,27 @@ const spawnSceneryAction: commandActionHandler = ({ player, args }) => { player.instance.spawnGameObject(locationObject); }; -const undoSceneryAction: commandActionHandler = (details) => { +const undoSceneryAction: commandActionHandler = details => { const { player } = details; const o = player.metadata.lastSpawnedScenery; - if(!o) { + if (!o) { return; } player.instance.despawnGameObject(o); delete player.metadata.lastSpawnedScenery; - if(player.metadata.spawnedScenery) { + if (player.metadata.spawnedScenery) { player.metadata.spawnedScenery.pop(); } }; -const dumpSceneryAction: commandActionHandler = (details) => { +const dumpSceneryAction: commandActionHandler = details => { const { player } = details; - const path = `data/dump/scene-${ new Date().getTime() }.yml`; + const path = `data/dump/scene-${new Date().getTime()}.yml`; writeFileSync(path, dump(player.metadata.spawnedScenery)); logger.info(path); player.metadata.spawnedScenery = []; @@ -76,32 +76,34 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'scene', 'sc' ], + commands: ['scene', 'sc'], args: [ { name: 'locationObjectSearch', - type: 'string' + type: 'string', }, { name: 'objectOrientation', type: 'number', - defaultValue: 0 + defaultValue: 0, }, { name: 'objectType', type: 'number', - defaultValue: 10 - } + defaultValue: 10, + }, ], - handler: spawnSceneryAction - }, { + handler: spawnSceneryAction, + }, + { type: 'player_command', - commands: [ 'undoscene', 'undosc' ], - handler: undoSceneryAction - }, { + commands: ['undoscene', 'undosc'], + handler: undoSceneryAction, + }, + { type: 'player_command', - commands: [ 'dumpscene', 'dumpsc' ], - handler: dumpSceneryAction - } - ] + commands: ['dumpscene', 'dumpsc'], + handler: dumpSceneryAction, + }, + ], }; diff --git a/src/plugins/commands/spawn-test-players-command.plugin.ts b/src/plugins/commands/spawn-test-players-command.plugin.ts index df60b1d8e..70c48ac47 100644 --- a/src/plugins/commands/spawn-test-players-command.plugin.ts +++ b/src/plugins/commands/spawn-test-players-command.plugin.ts @@ -1,14 +1,13 @@ -import { Position } from '@engine/world/position'; -import { Player } from '@engine/world/actor/player/player'; import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { activeWorld } from '@engine/world'; +import { Player } from '@engine/world/actor/player/player'; +import { Position } from '@engine/world/position'; import { World } from '@engine/world/world'; - const handler: commandActionHandler = ({ player, args }) => { const playerCount = args.playerCount as number; - if(playerCount > World.MAX_PLAYERS - 1) { + if (playerCount > World.MAX_PLAYERS - 1) { player.sendMessage(`Error: Max player count is ${World.MAX_PLAYERS - 1}.`); return; } @@ -21,20 +20,20 @@ const handler: commandActionHandler = ({ player, args }) => { const spawnChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(x, y, 0)); const worldSlotsRemaining = activeWorld.playerSlotsRemaining() - 1; - if(worldSlotsRemaining <= 0) { + if (worldSlotsRemaining <= 0) { player.sendMessage(`Error: The game world is full.`); return; } const playerSpawnCount = playerCount > worldSlotsRemaining ? worldSlotsRemaining : playerCount; - if(playerSpawnCount < playerCount) { + if (playerSpawnCount < playerCount) { player.sendMessage(`Warning: There was only room for ${playerSpawnCount}/${playerCount} player spawns.`); } // TODO (JameskmongeR) what's the difference between this and `generateFakePlayers` - for(let i = 0; i < playerSpawnCount; i++) { + for (let i = 0; i < playerSpawnCount; i++) { // TODO (Jameskmonger) we should be able to create a player without a connection, and without passing nulls in const testPlayer = new Player(null as any, null as any, null as any, i, `test${i}`, 'abs', true); activeWorld.registerPlayer(testPlayer); @@ -42,7 +41,7 @@ const handler: commandActionHandler = ({ player, args }) => { xOffset++; - if(xOffset > 20) { + if (xOffset > 20) { xOffset = 0; yOffset--; } @@ -50,7 +49,7 @@ const handler: commandActionHandler = ({ player, args }) => { testPlayer.position = new Position(x + xOffset, y + yOffset, 0); const newChunk = activeWorld.chunkManager.getChunkForWorldPosition(testPlayer.position); - if(!spawnChunk.equals(newChunk)) { + if (!spawnChunk.equals(newChunk)) { spawnChunk.removePlayer(testPlayer); newChunk.addPlayer(testPlayer); } @@ -59,20 +58,19 @@ const handler: commandActionHandler = ({ player, args }) => { } }; - export default { pluginId: 'rs:spawn_test_players_command', hooks: [ { type: 'player_command', - commands: [ 'spawn_players', 'spawnplayers' ], + commands: ['spawn_players', 'spawnplayers'], args: [ { name: 'playerCount', - type: 'number' - } + type: 'number', + }, ], - handler - } - ] + handler, + }, + ], }; diff --git a/src/plugins/commands/stat-commands.plugin.ts b/src/plugins/commands/stat-commands.plugin.ts index 3f5017a97..59c65fa3b 100644 --- a/src/plugins/commands/stat-commands.plugin.ts +++ b/src/plugins/commands/stat-commands.plugin.ts @@ -2,15 +2,15 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.ac const setLevelAction: commandActionHandler = ({ player, args }) => { const skillId = args?.skillId || null; - const level: number | null = args?.level as number || null; + const level: number | null = (args?.level as number) || null; - if(!skillId || !level) { + if (!skillId || !level) { player.sendMessage(`Invalid syntax: Use ::setlevel skill_id skill_level`); return; } const skill = player.skills[skillId]; - if(!skill) { + if (!skill) { player.sendMessage(`Skill ${skillId} not found.`); return; } @@ -26,18 +26,18 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'setlevel', 'setlvl' ], + commands: ['setlevel', 'setlvl'], args: [ { name: 'skillId', - type: 'string' + type: 'string', }, { name: 'level', - type: 'number' - } + type: 'number', + }, ], - handler: setLevelAction - } - ] + handler: setLevelAction, + }, + ], }; diff --git a/src/plugins/commands/teleport-command.plugin.ts b/src/plugins/commands/teleport-command.plugin.ts index 8e2260d75..9ad6b807d 100644 --- a/src/plugins/commands/teleport-command.plugin.ts +++ b/src/plugins/commands/teleport-command.plugin.ts @@ -2,14 +2,14 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.ac import { activeWorld } from '@engine/world'; import { Position } from '@engine/world/position'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const x = args.XorPlayerName; - if(typeof x === 'string') { + if (typeof x === 'string') { const playerWithName = activeWorld.findPlayer(x); - if(playerWithName) { + if (playerWithName) { player.teleport(playerWithName.position); return; } @@ -17,7 +17,7 @@ const action: commandActionHandler = (details) => { const xCoord: number = typeof x === 'string' ? parseInt(x, 10) : x; - if(isNaN(xCoord)) { + if (isNaN(xCoord)) { return; } const y: number = args.y as number; @@ -31,24 +31,24 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'move', 'goto', 'teleport', 'tele', 'moveto', 'setpos' ], + commands: ['move', 'goto', 'teleport', 'tele', 'moveto', 'setpos'], args: [ { name: 'XorPlayerName', - type: 'string' + type: 'string', }, { name: 'y', type: 'number', - defaultValue: 3222 + defaultValue: 3222, }, { name: 'level', type: 'number', - defaultValue: 0 - } + defaultValue: 0, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/transform-command.plugin.ts b/src/plugins/commands/transform-command.plugin.ts index 4ae91e920..14d322111 100644 --- a/src/plugins/commands/transform-command.plugin.ts +++ b/src/plugins/commands/transform-command.plugin.ts @@ -1,9 +1,9 @@ -import type { commandActionHandler, PlayerCommandActionHook } from '@engine/action/pipe/player-command.action'; +import type { PlayerCommandActionHook, commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; - player.transformInto(details && details.args ? details.args['npcKey'] : null) + player.transformInto(details && details.args ? details.args['npcKey'] : null); }; export default { @@ -11,15 +11,15 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'transform' ], + commands: ['transform'], args: [ { name: 'npcKey', type: 'either', - defaultValue: undefined - } + defaultValue: undefined, + }, ], - handler: action - } as PlayerCommandActionHook - ] + handler: action, + } as PlayerCommandActionHook, + ], }; diff --git a/src/plugins/commands/travel-back-command.plugin.ts b/src/plugins/commands/travel-back-command.plugin.ts index fac21ca51..1c91ddd3c 100644 --- a/src/plugins/commands/travel-back-command.plugin.ts +++ b/src/plugins/commands/travel-back-command.plugin.ts @@ -1,6 +1,6 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player } = details; if (player.metadata.lastPosition) { @@ -13,8 +13,8 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'back' ], - handler: action - } - ] + commands: ['back'], + handler: action, + }, + ], }; diff --git a/src/plugins/commands/travel-command.plugin.ts b/src/plugins/commands/travel-command.plugin.ts index ca8ca338c..544d7e62d 100644 --- a/src/plugins/commands/travel-command.plugin.ts +++ b/src/plugins/commands/travel-command.plugin.ts @@ -1,8 +1,8 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -import type { TravelLocation } from '@engine/world/config/travel-locations'; import { activeWorld } from '@engine/world'; +import type { TravelLocation } from '@engine/world/config/travel-locations'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const search: string = args.search as string; @@ -21,14 +21,14 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'travel' ], + commands: ['travel'], args: [ { name: 'search', - type: 'string' - } + type: 'string', + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/commands/widget-commands.plugin.ts b/src/plugins/commands/widget-commands.plugin.ts index 9f0241e23..5c7383b38 100644 --- a/src/plugins/commands/widget-commands.plugin.ts +++ b/src/plugins/commands/widget-commands.plugin.ts @@ -1,23 +1,23 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; -const action: commandActionHandler = (details) => { +const action: commandActionHandler = details => { const { player, args } = details; const widgetId: number = args.widgetId as number; const secondaryWidgetId: number = args.secondaryWidgetId as number; - if(secondaryWidgetId === 1) { + if (secondaryWidgetId === 1) { player.interfaceState.openWidget(widgetId, { - slot: 'screen' + slot: 'screen', }); } else { player.interfaceState.openWidget(widgetId, { slot: 'screen', - multi: true + multi: true, }); player.interfaceState.openWidget(secondaryWidgetId, { slot: 'tabarea', - multi: true + multi: true, }); } }; @@ -27,19 +27,19 @@ export default { hooks: [ { type: 'player_command', - commands: [ 'widget' ], + commands: ['widget'], args: [ { name: 'widgetId', - type: 'number' + type: 'number', }, { name: 'secondaryWidgetId', type: 'number', - defaultValue: 1 - } + defaultValue: 1, + }, ], - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/dialogue/dialogue-option.plugin.ts b/src/plugins/dialogue/dialogue-option.plugin.ts index 079a9f400..bb1a6d75d 100644 --- a/src/plugins/dialogue/dialogue-option.plugin.ts +++ b/src/plugins/dialogue/dialogue-option.plugin.ts @@ -1,16 +1,11 @@ import type { widgetInteractionActionHandler } from '@engine/action/pipe/widget-interaction.action'; -const dialogueIds = [ - 64, 65, 66, 67, 241, - 242, 243, 244, 228, 230, - 232, 234, - 210, 211, 212, 213, 214, -]; +const dialogueIds = [64, 65, 66, 67, 241, 242, 243, 244, 228, 230, 232, 234, 210, 211, 212, 213, 214]; /** * Handles a basic NPC/Player/Option/Text dialogue choice/action. */ -export const action: widgetInteractionActionHandler = (details) => { +export const action: widgetInteractionActionHandler = details => { const { player, widgetId, childId } = details; player.interfaceState.closeWidget('chatbox', widgetId, childId); }; @@ -22,7 +17,7 @@ export default { type: 'widget_interaction', widgetIds: dialogueIds, handler: action, - cancelActions: true - } - ] + cancelActions: true, + }, + ], }; diff --git a/src/plugins/dialogue/item-selection.plugin.ts b/src/plugins/dialogue/item-selection.plugin.ts index 784c8d321..f7cd20918 100644 --- a/src/plugins/dialogue/item-selection.plugin.ts +++ b/src/plugins/dialogue/item-selection.plugin.ts @@ -3,7 +3,7 @@ import type { widgetInteractionActionHandler } from '@engine/action/pipe/widget- /** * Handles an item selection dialogue choice. */ -export const action: widgetInteractionActionHandler = (details) => { +export const action: widgetInteractionActionHandler = details => { const { player, widgetId, childId } = details; player.interfaceState.closeWidget('chatbox', widgetId, childId); }; @@ -13,9 +13,9 @@ export default { hooks: [ { type: 'widget_interaction', - widgetIds: [ 303, 304, 305, 306, 307, 309 ], + widgetIds: [303, 304, 305, 306, 307, 309], handler: action, - cancelActions: false - } - ] + cancelActions: false, + }, + ], }; diff --git a/src/plugins/items/buckets/empty-container.plugin.ts b/src/plugins/items/buckets/empty-container.plugin.ts index 8f6edc77b..01957479c 100644 --- a/src/plugins/items/buckets/empty-container.plugin.ts +++ b/src/plugins/items/buckets/empty-container.plugin.ts @@ -1,16 +1,16 @@ -import { soundIds } from '@engine/world/config/sound-ids'; +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config/config-handler'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; -export const handler: itemInteractionActionHandler = (details) => { +export const handler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot } = details; const inventory = player.inventory; const item = getItemFromContainer(itemId, itemSlot, inventory); - if(!item) { + if (!item) { // The specified item was not found in the specified slot. return; } @@ -37,9 +37,9 @@ export default { type: 'item_interaction', widgets: widgets.inventory, options: 'empty', - itemIds: [ itemIds.bucketOfMilk, itemIds.bucketOfWater, itemIds.jugOfWater ], + itemIds: [itemIds.bucketOfMilk, itemIds.bucketOfWater, itemIds.jugOfWater], handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/buckets/fill-container.plugin.ts b/src/plugins/items/buckets/fill-container.plugin.ts index 3b6220dc7..f0f38f701 100644 --- a/src/plugins/items/buckets/fill-container.plugin.ts +++ b/src/plugins/items/buckets/fill-container.plugin.ts @@ -1,14 +1,14 @@ -import { itemIds } from '@engine/world/config/item-ids'; +import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; +import { findItem } from '@engine/config/config-handler'; import { animationIds } from '@engine/world/config/animation-ids'; +import { itemIds } from '@engine/world/config/item-ids'; import { soundIds } from '@engine/world/config/sound-ids'; -import { findItem } from '@engine/config/config-handler'; import { logger } from '@runejs/common'; -import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; const FountainIds: number[] = [879]; const SinkIds: number[] = [14878, 873]; const WellIds: number[] = [878]; -export const handler: itemOnObjectActionHandler = (details) => { +export const handler: itemOnObjectActionHandler = details => { const { player, objectConfig, item } = details; const itemDef = findItem(item.itemId); @@ -34,14 +34,12 @@ export const handler: itemOnObjectActionHandler = (details) => { break; } - const objectName = details.objectConfig.name || ''; if (!objectName) { logger.warn(`Fill container object ${details.object.objectId} has no name.`); } player.sendMessage(`You fill the ${itemDef.name.toLowerCase()} from the ${objectName.toLowerCase()}.`); - }; export default { @@ -49,10 +47,10 @@ export default { hooks: [ { type: 'item_on_object', - objectIds: [ ...FountainIds, ...WellIds, ...SinkIds ], - itemIds: [ itemIds.bucket, itemIds.jug ], + objectIds: [...FountainIds, ...WellIds, ...SinkIds], + itemIds: [itemIds.bucket, itemIds.jug], walkTo: true, - handler - } - ] + handler, + }, + ], }; diff --git a/src/plugins/items/capes/skillcape-emotes.plugin.ts b/src/plugins/items/capes/skillcape-emotes.plugin.ts index 38248c65d..8f97c808c 100644 --- a/src/plugins/items/capes/skillcape-emotes.plugin.ts +++ b/src/plugins/items/capes/skillcape-emotes.plugin.ts @@ -1,17 +1,18 @@ -import { lockEmote, unlockEmote } from '@plugins/buttons/player-emotes.plugin'; -import { itemIds } from '@engine/world/config/item-ids'; import type { equipmentChangeActionHandler } from '@engine/action/pipe/equipment-change.action'; +import { itemIds } from '@engine/world/config/item-ids'; +import { lockEmote, unlockEmote } from '@plugins/buttons/player-emotes.plugin'; -export const skillcapeIds: Array = Object.keys( - itemIds.skillCapes).flatMap(skill => [itemIds.skillCapes[skill].untrimmed, itemIds.skillCapes[skill].trimmed] -); +export const skillcapeIds: Array = Object.keys(itemIds.skillCapes).flatMap(skill => [ + itemIds.skillCapes[skill].untrimmed, + itemIds.skillCapes[skill].trimmed, +]); -export const equip: equipmentChangeActionHandler = (details) => { +export const equip: equipmentChangeActionHandler = details => { const { player } = details; unlockEmote(player, 'SKILLCAPE'); }; -export const unequip: equipmentChangeActionHandler = (details) => { +export const unequip: equipmentChangeActionHandler = details => { const { player } = details; lockEmote(player, 'SKILLCAPE'); player.stopAnimation(); @@ -25,12 +26,13 @@ export default { type: 'equipment_change', eventType: 'equip', handler: equip, - itemIds: skillcapeIds - }, { + itemIds: skillcapeIds, + }, + { type: 'equipment_change', eventType: 'unequip', handler: unequip, - itemIds: skillcapeIds - } - ] + itemIds: skillcapeIds, + }, + ], }; diff --git a/src/plugins/items/consumables/eating.plugin.ts b/src/plugins/items/consumables/eating.plugin.ts index f8aa9bd9e..bfc4a87ac 100644 --- a/src/plugins/items/consumables/eating.plugin.ts +++ b/src/plugins/items/consumables/eating.plugin.ts @@ -1,38 +1,37 @@ +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import { findItem, widgets } from '@engine/config/config-handler'; +import { randomBetween } from '@engine/util/num'; import type { SkillName } from '@engine/world/actor/skills'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; -import { randomBetween } from '@engine/util/num'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; - -export const action: itemInteractionActionHandler = (details) => { +export const action: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, itemDetails } = details; - if(!itemDetails.consumable) { + if (!itemDetails.consumable) { player.sendMessage('Item is not registered as consumable!'); return; } - if(!itemDetails.metadata.consume_effects) { + if (!itemDetails.metadata.consume_effects) { player.sendMessage('Item is missing consume effects!'); return; } - if(!itemDetails.metadata.consume_effects.clock) { + if (!itemDetails.metadata.consume_effects.clock) { player.sendMessage('Item is missing clock!'); return; } - if(itemDetails.metadata.consume_effects.special){ + if (itemDetails.metadata.consume_effects.special) { player.sendMessage('Cannot handle special foods yet!'); return; } - const clock = 'clock_'+itemDetails.metadata.consume_effects.clock; + const clock = 'clock_' + itemDetails.metadata.consume_effects.clock; // Check if player recently ate - if(player.metadata[clock]){ + if (player.metadata[clock]) { return; } const inventoryItem = player.inventory.items[itemSlot]; - if(!inventoryItem || inventoryItem.itemId !== itemId){ + if (!inventoryItem || inventoryItem.itemId !== itemId) { return; } @@ -40,14 +39,13 @@ export const action: itemInteractionActionHandler = (details) => { ? findItem(itemDetails.metadata.consume_effects.replaced_by) : null; - if(replacementItemDetails) { + if (replacementItemDetails) { player.inventory.items[itemSlot] = { itemId: replacementItemDetails.gameId, amount: 1 }; } else { player.inventory.items[itemSlot] = null; } player.playSound(soundIds.eat); - player.playAnimation(animationIds.eat) - + player.playAnimation(animationIds.eat); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); @@ -60,44 +58,40 @@ export const action: itemInteractionActionHandler = (details) => { // player.metadata[clock] = false; // }, World.TICK_LENGTH * 3); - if(itemDetails.metadata.consume_effects.energy) { + if (itemDetails.metadata.consume_effects.energy) { // TODO: Give player run energy } - if(itemDetails.metadata.consume_effects.skills) { + if (itemDetails.metadata.consume_effects.skills) { const skillModifiers = itemDetails.metadata.consume_effects.skills; for (const sk in skillModifiers) { const skill: SkillName = sk as SkillName; let value; - if (Array.isArray(skillModifiers[skill])){ + if (Array.isArray(skillModifiers[skill])) { value = randomBetween(skillModifiers[skill][0], skillModifiers[skill][1]); } else { value = skillModifiers[skill]; } - const playerSkill = player.skills[skill]; + const playerSkill = player.skills[skill]; const maxLevel = playerSkill.levelForExp; const currentLevel = playerSkill.level || playerSkill.levelForExp; - if(skill === 'hitpoints') { + if (skill === 'hitpoints') { let newHealth: number = currentLevel + value; - if(newHealth > maxLevel) { + if (newHealth > maxLevel) { newHealth = maxLevel; } playerSkill.level = newHealth; - player.sendMessage(`You eat the ${itemDetails.name}, and it restores ${newHealth - currentLevel} health.`) + player.sendMessage(`You eat the ${itemDetails.name}, and it restores ${newHealth - currentLevel} health.`); } else { - let newLevel: number = currentLevel + value; - if(newLevel > maxLevel + value) { + let newLevel: number = currentLevel + value; + if (newLevel > maxLevel + value) { newLevel = maxLevel + value; } playerSkill.level = newLevel; } player.outgoingPackets.updateSkill(player.skills.getSkillId(skill), playerSkill.level, playerSkill.exp); - } } - - - }; export default { @@ -108,7 +102,7 @@ export default { widgets: widgets.inventory, options: 'eat', handler: action, - cancelOtherActions: true - } - ] + cancelOtherActions: true, + }, + ], }; diff --git a/src/plugins/items/drop-item.plugin.ts b/src/plugins/items/drop-item.plugin.ts index 4cac41df5..971b41d09 100644 --- a/src/plugins/items/drop-item.plugin.ts +++ b/src/plugins/items/drop-item.plugin.ts @@ -1,40 +1,45 @@ +import type { ActionCancelType } from '@engine/action/action-pipeline'; +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; +import { dialogue, execute } from '@engine/world/actor/dialogue'; +import { Rights } from '@engine/world/actor/player/player'; import { soundIds } from '@engine/world/config/sound-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; import { serverConfig } from '@server/game/game-server'; -import { Rights } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; -import { dialogue, execute } from '@engine/world/actor/dialogue'; -import type { ActionCancelType } from '@engine/action/action-pipeline'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; export const handler: itemInteractionActionHandler = ({ player, itemId, itemSlot }) => { const inventory = player.inventory; const item = getItemFromContainer(itemId, itemSlot, inventory); - if(!item) { + if (!item) { // The specified item was not found in the specified slot. return; } - if(!serverConfig.adminDropsEnabled && player.rights === Rights.ADMIN) { - dialogue([ player ], [ - text => ('Administrators are not allowed to drop items.'), - options => [ - `Destroy the item!`, [ - execute(() => { - inventory.remove(itemSlot); - player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null); - }), + if (!serverConfig.adminDropsEnabled && player.rights === Rights.ADMIN) { + dialogue( + [player], + [ + text => 'Administrators are not allowed to drop items.', + options => [ + `Destroy the item!`, + [ + execute(() => { + inventory.remove(itemSlot); + player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null); + }), + ], + `Bank the item!`, + [ + execute(() => { + inventory.remove(itemSlot); + player.bank.add(item); + player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null); + }), + ], ], - `Bank the item!`, [ - execute(() => { - inventory.remove(itemSlot); - player.bank.add(item); - player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null); - }), - ] - ] - ]); + ], + ); return; } @@ -55,7 +60,7 @@ export default { widgets: widgets.inventory, options: 'drop', handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/equipment/equip-item.plugin.ts b/src/plugins/items/equipment/equip-item.plugin.ts index 2a60dd2d4..703376f91 100644 --- a/src/plugins/items/equipment/equip-item.plugin.ts +++ b/src/plugins/items/equipment/equip-item.plugin.ts @@ -1,10 +1,10 @@ import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import { widgets } from '@engine/config/config-handler'; -export const handler: itemInteractionActionHandler = (details) => { +export const handler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, itemDetails } = details; - if(!itemDetails) { + if (!itemDetails) { // The item is not yet configured on the server. player.sendMessage(`Item ${itemId} is not yet configured on the server.`); return; @@ -21,7 +21,7 @@ export default { widgets: widgets.inventory, options: 'equip', handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/equipment/equipment-stats.plugin.ts b/src/plugins/items/equipment/equipment-stats.plugin.ts index 34fb8fb9f..17b344574 100644 --- a/src/plugins/items/equipment/equipment-stats.plugin.ts +++ b/src/plugins/items/equipment/equipment-stats.plugin.ts @@ -1,7 +1,7 @@ import type { buttonActionHandler } from '@engine/action/pipe/button.action'; import { widgets } from '@engine/config/config-handler'; -export const handler: buttonActionHandler = (details) => { +export const handler: buttonActionHandler = details => { const { player } = details; player.updateBonuses(); @@ -12,17 +12,15 @@ export const handler: buttonActionHandler = (details) => { player.interfaceState.openWidget(widgets.equipmentStats.widgetId, { multi: true, - slot: 'screen' + slot: 'screen', }); player.interfaceState.openWidget(widgets.inventory.widgetId, { multi: true, - slot: 'tabarea' + slot: 'tabarea', }); }; export default { pluginId: 'rs:equipment_stat_view', - hooks: [ - { type: 'button', widgetId: widgets.equipment.widgetId, buttonIds: 24, handler } - ] + hooks: [{ type: 'button', widgetId: widgets.equipment.widgetId, buttonIds: 24, handler }], }; diff --git a/src/plugins/items/equipment/unequip-item.plugin.ts b/src/plugins/items/equipment/unequip-item.plugin.ts index 31e7f6a33..eea3a1ea6 100644 --- a/src/plugins/items/equipment/unequip-item.plugin.ts +++ b/src/plugins/items/equipment/unequip-item.plugin.ts @@ -1,19 +1,19 @@ -import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config/config-handler'; import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; +import { getItemFromContainer } from '@engine/world/items/item-container'; -export const handler: itemInteractionActionHandler = (details) => { +export const handler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, itemDetails } = details; const equipment = player.equipment; const item = getItemFromContainer(itemId, itemSlot, equipment); - if(!item) { + if (!item) { // The specified item was not found in the specified slot. return; } - if(!itemDetails) { + if (!itemDetails) { // The item is not yet configured on the server. player.sendMessage(`Item ${itemId} is not yet configured on the server.`); return; @@ -27,13 +27,10 @@ export default { hooks: [ { type: 'item_interaction', - widgets: [ - widgets.equipment, - widgets.equipmentStats - ], + widgets: [widgets.equipment, widgets.equipmentStats], options: 'remove', handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/herblore/clean-herb.ts b/src/plugins/items/herblore/clean-herb.ts index 785b48f6d..d3292f01d 100644 --- a/src/plugins/items/herblore/clean-herb.ts +++ b/src/plugins/items/herblore/clean-herb.ts @@ -1,8 +1,8 @@ +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import { findItem, widgets } from '@engine/config/config-handler'; -import { soundIds } from '@engine/world/config/sound-ids'; import type { ItemDetails } from '@engine/config/item-config'; +import { soundIds } from '@engine/world/config/sound-ids'; import { logger } from '@runejs/common'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; interface IGrimyHerb { grimy: ItemDetails; @@ -21,96 +21,95 @@ const herbs: IGrimyHerb[] = [ grimy: findItem('rs:grimy_guam')!, clean: findItem('rs:herb_guam')!, level: 3, - experience: 2.5 + experience: 2.5, }, { grimy: findItem('rs:grimy_marrentill')!, clean: findItem('rs:herb_marrentill')!, level: 5, - experience: 3.8 + experience: 3.8, }, { grimy: findItem('rs:grimy_tarromin')!, clean: findItem('rs:herb_tarromin')!, level: 11, - experience: 5 + experience: 5, }, { grimy: findItem('rs:grimy_harralander')!, clean: findItem('rs:herb_harralander')!, level: 20, - experience: 6.3 + experience: 6.3, }, { grimy: findItem('rs:grimy_ranarr')!, clean: findItem('rs:herb_ranarr')!, level: 25, - experience: 7.5 + experience: 7.5, }, { grimy: findItem('rs:grimy_toadflax')!, clean: findItem('rs:herb_toadflax')!, level: 30, - experience: 8 + experience: 8, }, { grimy: findItem('rs:grimy_irit')!, clean: findItem('rs:herb_irit')!, level: 40, - experience: 8.8 + experience: 8.8, }, { grimy: findItem('rs:grimy_avantoe')!, clean: findItem('rs:herb_avantoe')!, level: 48, - experience: 10 + experience: 10, }, { grimy: findItem('rs:grimy_kwuarm')!, clean: findItem('rs:herb_kwuarm')!, level: 54, - experience: 11.3 + experience: 11.3, }, { grimy: findItem('rs:grimy_snapdragon')!, clean: findItem('rs:herb_snapdragon')!, level: 59, - experience: 11.8 + experience: 11.8, }, { grimy: findItem('rs:grimy_cadantine')!, clean: findItem('rs:herb_cadantine')!, level: 65, - experience: 12.5 + experience: 12.5, }, { grimy: findItem('rs:grimy_lantadyme')!, clean: findItem('rs:herb_lantadyme')!, level: 67, - experience: 13.1 + experience: 13.1, }, { grimy: findItem('rs:grimy_dwarf_weed')!, clean: findItem('rs:herb_dwarf_weed')!, level: 70, - experience: 13.8 + experience: 13.8, }, { grimy: findItem('rs:grimy_torstol')!, clean: findItem('rs:herb_torstol')!, level: 75, - experience: 15 + experience: 15, }, -] - +]; export const action: itemInteractionActionHandler = details => { const { player, itemId, itemSlot } = details; - const herb = herbs.find((herb) => herb.grimy.gameId === itemId); - if(!herb) { + const herb = herbs.find(herb => herb.grimy.gameId === itemId); + if (!herb) { return; } - if(!player.skills.hasLevel('herblore', herb.level)) { + if (!player.skills.hasLevel('herblore', herb.level)) { player.sendMessage(`You need a Herblore level of ${herb.level} to identify this herb.`, true); return; } @@ -138,7 +137,7 @@ export default { type: 'item_action', widgets: widgets.inventory, options: 'identify', - itemIds: herbs.map((herb) => herb.grimy.gameId), + itemIds: herbs.map(herb => herb.grimy.gameId), action, - cancelOtherActions: true + cancelOtherActions: true, }; diff --git a/src/plugins/items/move-item.plugin.ts b/src/plugins/items/move-item.plugin.ts index 005404a49..35d30e8e6 100644 --- a/src/plugins/items/move-item.plugin.ts +++ b/src/plugins/items/move-item.plugin.ts @@ -1,25 +1,30 @@ -import type { ItemContainer } from '@engine/world/items/item-container'; -import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import type { itemSwapActionHandler } from '@engine/action/pipe/item-swap.action'; +import { widgets } from '@engine/config/config-handler'; +import type { Player } from '@engine/world/actor/player/player'; +import type { ItemContainer } from '@engine/world/items/item-container'; -type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; +type WidgetDetail = [number, number, (player: Player) => ItemContainer]; const movableWidgets: WidgetDetail[] = [ // Player Bank Screen - [ widgets.bank.screenWidget.widgetId, widgets.bank.screenWidget.containerId, player => player.bank ] + [widgets.bank.screenWidget.widgetId, widgets.bank.screenWidget.containerId, player => player.bank], ]; -function moveItem(player: Player, container: ItemContainer, widget: { widgetId: number, containerId: number }, - fromSlot: number, toSlot: number): void { - if(toSlot > container.size - 1 || fromSlot > container.size - 1) { +function moveItem( + player: Player, + container: ItemContainer, + widget: { widgetId: number; containerId: number }, + fromSlot: number, + toSlot: number, +): void { + if (toSlot > container.size - 1 || fromSlot > container.size - 1) { return; } - if(fromSlot < toSlot) { + if (fromSlot < toSlot) { let slot = toSlot; let current = container.remove(fromSlot); - while(slot >= fromSlot) { + while (slot >= fromSlot) { const temp = container.remove(slot); container.set(slot, current); current = temp; @@ -28,7 +33,7 @@ function moveItem(player: Player, container: ItemContainer, widget: { widgetId: } else { let slot = toSlot; let current = container.remove(fromSlot); - while(slot <= fromSlot) { + while (slot <= fromSlot) { const temp = container.remove(slot); container.set(slot, current); current = temp; @@ -39,11 +44,11 @@ function moveItem(player: Player, container: ItemContainer, widget: { widgetId: player.outgoingPackets.sendUpdateAllWidgetItems(widget, container); } -export const action: itemSwapActionHandler = (details) => { +export const action: itemSwapActionHandler = details => { const { player, widgetId, containerId, fromSlot, toSlot } = details; const widgetDetails = movableWidgets.filter(widgetDetail => widgetDetail[0] === widgetId && widgetDetail[1] === containerId); - if(widgetDetails && widgetDetails[0]) { + if (widgetDetails && widgetDetails[0]) { const itemContainer: ItemContainer = widgetDetails[0][2](player); moveItem(player, itemContainer, { widgetId, containerId }, fromSlot, toSlot); } @@ -55,7 +60,7 @@ export default { { type: 'move_item', widgetIds: movableWidgets.map(widgetDetails => widgetDetails[0]), - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/items/pickup-item.plugin.ts b/src/plugins/items/pickup-item.plugin.ts index c695d552e..c809b8060 100644 --- a/src/plugins/items/pickup-item.plugin.ts +++ b/src/plugins/items/pickup-item.plugin.ts @@ -1,21 +1,20 @@ -import type { Item } from '@engine/world/items/item'; -import { soundIds } from '@engine/world/config/sound-ids'; +import type { ActionCancelType } from '@engine/action/action-pipeline'; +import type { spawnedItemInteractionHandler } from '@engine/action/pipe/spawned-item-interaction.action'; import { widgets } from '@engine/config/config-handler'; +import { soundIds } from '@engine/world/config/sound-ids'; +import type { Item } from '@engine/world/items/item'; import { logger } from '@runejs/common'; -import type { spawnedItemInteractionHandler } from '@engine/action/pipe/spawned-item-interaction.action'; -import type { ActionCancelType } from '@engine/action/action-pipeline'; - export const handler: spawnedItemInteractionHandler = ({ player, worldItem, itemDetails }) => { const inventory = player.inventory; const amount = worldItem.amount; - let slot = -1 + let slot = -1; - if(itemDetails.stackable) { + if (itemDetails.stackable) { const existingItemIndex = inventory.findIndex(worldItem.itemId); - if(existingItemIndex !== -1) { + if (existingItemIndex !== -1) { const existingItem = inventory.items[existingItemIndex]; - if(existingItem && (existingItem.amount + worldItem.amount >= 2147483647)) { + if (existingItem && existingItem.amount + worldItem.amount >= 2147483647) { // @TODO create new item stack return; } else { @@ -24,11 +23,11 @@ export const handler: spawnedItemInteractionHandler = ({ player, worldItem, item } } - if(slot === -1) { + if (slot === -1) { slot = inventory.getFirstOpenSlot(); } - if(slot === -1) { + if (slot === -1) { player.sendMessage(`You don't have enough free space to do that.`); return; } @@ -42,7 +41,7 @@ export const handler: spawnedItemInteractionHandler = ({ player, worldItem, item const item: Item = { itemId: worldItem.itemId, - amount + amount, }; const addedItem = inventory.add(item); @@ -65,7 +64,7 @@ export default { type: 'spawned_item_interaction', options: 'pick-up', handler, - walkTo: true - } - ] + walkTo: true, + }, + ], }; diff --git a/src/plugins/items/pots/empty-pot.plugin.ts b/src/plugins/items/pots/empty-pot.plugin.ts index 7fde863ae..3ce57088a 100644 --- a/src/plugins/items/pots/empty-pot.plugin.ts +++ b/src/plugins/items/pots/empty-pot.plugin.ts @@ -1,10 +1,10 @@ -import { soundIds } from '@engine/world/config/sound-ids'; +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config/config-handler'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; -export const action: itemInteractionActionHandler = (details) => { +export const action: itemInteractionActionHandler = details => { const { player, itemId, itemSlot } = details; const inventory = player.inventory; @@ -27,9 +27,9 @@ export default { type: 'item_interaction', widgets: widgets.inventory, options: 'empty', - itemIds: [ itemIds.potOfFlour ], + itemIds: [itemIds.potOfFlour], handler: action, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts index 2a0f3700a..582f6ef24 100644 --- a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts +++ b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts @@ -1,8 +1,8 @@ +import type { ItemOnItemAction } from '@engine/action/pipe/item-on-item.action'; +import type { WidgetInteractionAction } from '@engine/action/pipe/widget-interaction.action'; import { findItem, widgets } from '@engine/config/config-handler'; import type { ItemDetails } from '@engine/config/item-config'; import { Rights } from '@engine/world/actor/player/player'; -import type { ItemOnItemAction } from '@engine/action/pipe/item-on-item.action'; -import type { WidgetInteractionAction } from '@engine/action/pipe/widget-interaction.action'; /** * The rotten potato item. @@ -11,9 +11,8 @@ import type { WidgetInteractionAction } from '@engine/action/pipe/widget-interac */ export const RottenPotatoItem: ItemDetails = findItem('rs:rotten_potato')!; - export const ExecuteIfAdmin = (details: ItemOnItemAction | WidgetInteractionAction, callback) => { - if(details.player.rights === Rights.ADMIN) { + if (details.player.rights === Rights.ADMIN) { callback(details); return; } @@ -21,5 +20,4 @@ export const ExecuteIfAdmin = (details: ItemOnItemAction | WidgetInteractionActi details.player.inventory.removeFirst(RottenPotatoItem.gameId, false); } details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); - -} +}; diff --git a/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts b/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts index c98c31f2d..b7a193da5 100644 --- a/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts +++ b/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts @@ -1,165 +1,161 @@ -import type { Player } from '@engine/world/actor/player/player'; -import { activeWorld } from '@engine/world'; import type { widgetInteractionActionHandler } from '@engine/action/pipe/widget-interaction.action'; +import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; const INTRO_PAGE_COUNT = 1; const ITEMS_PER_PAGE = 15; -const pageCount = INTRO_PAGE_COUNT + Math.round(activeWorld.travelLocations.locations.length / (ITEMS_PER_PAGE)); +const pageCount = INTRO_PAGE_COUNT + Math.round(activeWorld.travelLocations.locations.length / ITEMS_PER_PAGE); export function openTravel(player: Player, page: number) { const widget = player.interfaceState.openWidget(27, { slot: 'screen', fakeWidget: 3100002, metadata: { - page: page - } + page: page, + }, }); // Prev page button player.modifyWidget(widget.widgetId, { childId: 95, - hidden: widget.metadata.page === 1 // hide prev page button if we are on the first page - }) - + hidden: widget.metadata.page === 1, // hide prev page button if we are on the first page + }); - const isLastPage = (p) => pageCount === page * 2 // 2 "pages" per page + const isLastPage = p => pageCount === page * 2; // 2 "pages" per page // Next page buttton player.modifyWidget(widget.widgetId, { childId: 97, - hidden: isLastPage(page) - }) + hidden: isLastPage(page), + }); // prev page label player.modifyWidget(widget.widgetId, { childId: 98, - text: widget.metadata.page * 2 -1 === 1 ? `` : `Page ${widget.metadata.page * 2 -1} ` - }) + text: widget.metadata.page * 2 - 1 === 1 ? `` : `Page ${widget.metadata.page * 2 - 1} `, + }); // next page label player.modifyWidget(widget.widgetId, { childId: 99, - text: `Page ${widget.metadata.page * 2} ` - }) + text: `Page ${widget.metadata.page * 2} `, + }); // clear default lines of both open pages - for (let i = 0; i < (ITEMS_PER_PAGE * 2); i++) { + for (let i = 0; i < ITEMS_PER_PAGE * 2; i++) { player.modifyWidget(widget.widgetId, { - childId: 33+i, + childId: 33 + i, text: '', - hidden: true - }) + hidden: true, + }); } - let currentLocation = ((ITEMS_PER_PAGE * 2) * ((page - INTRO_PAGE_COUNT) - 1) + (INTRO_PAGE_COUNT * ITEMS_PER_PAGE)); + let currentLocation = ITEMS_PER_PAGE * 2 * (page - INTRO_PAGE_COUNT - 1) + INTRO_PAGE_COUNT * ITEMS_PER_PAGE; const historyPage = [ 'Last locations', '', '', - ...(player.savedMetadata.lastTravel || new Array(10)).map((location: number | undefined) => location === undefined ? '' : activeWorld.travelLocations.locations[location]?.name), - ] + ...(player.savedMetadata.lastTravel || new Array(10)).map((location: number | undefined) => + location === undefined ? '' : activeWorld.travelLocations.locations[location]?.name, + ), + ]; - if(widget.metadata.page * 2 -1 === 1) { - for (let i = 0; i < ITEMS_PER_PAGE * 2; i+=2) { + if (widget.metadata.page * 2 - 1 === 1) { + for (let i = 0; i < ITEMS_PER_PAGE * 2; i += 2) { player.modifyWidget(widget.widgetId, { - childId: 101+i, + childId: 101 + i, text: historyPage[currentLocation + ITEMS_PER_PAGE] || '', - hidden: false - }) + hidden: false, + }); currentLocation++; } - } else{ - for (let i = 0; i < ITEMS_PER_PAGE * 2; i+=2) { + } else { + for (let i = 0; i < ITEMS_PER_PAGE * 2; i += 2) { player.modifyWidget(widget.widgetId, { - childId: 101+i, + childId: 101 + i, text: activeWorld.travelLocations.locations[currentLocation]?.name || '', - hidden: !activeWorld.travelLocations.locations[currentLocation]?.name - }) + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name, + }); currentLocation++; } - } - - - for (let i = 0; i < 30; i+=2) { + for (let i = 0; i < 30; i += 2) { player.modifyWidget(widget.widgetId, { - childId: 131+i-1, - hidden: !activeWorld.travelLocations.locations[currentLocation]?.name - }) + childId: 131 + i - 1, + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name, + }); player.modifyWidget(widget.widgetId, { - childId: 131+i, + childId: 131 + i, text: activeWorld.travelLocations.locations[currentLocation]?.name || '', - hidden: !activeWorld.travelLocations.locations[currentLocation]?.name - }) + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name, + }); currentLocation++; } - } -export const travelMenuInteract: widgetInteractionActionHandler = (details) => { +export const travelMenuInteract: widgetInteractionActionHandler = details => { const playerWidget = details.player.interfaceState.findWidget(27); - if(!playerWidget || !playerWidget.metadata.page) { + if (!playerWidget || !playerWidget.metadata.page) { return; } - switch (details.childId){ + switch (details.childId) { case 160: - openTravel(details.player, 1) + openTravel(details.player, 1); return; case 94: - openTravel(details.player, playerWidget.metadata.page-1) + openTravel(details.player, playerWidget.metadata.page - 1); return; case 96: - openTravel(details.player, playerWidget.metadata.page+1) + openTravel(details.player, playerWidget.metadata.page + 1); return; } let selectedIndex: number | undefined = undefined; - if(details.childId >= 101 && details.childId <= 129) { - selectedIndex = (details.childId - 99)/2 - 1; + if (details.childId >= 101 && details.childId <= 129) { + selectedIndex = (details.childId - 99) / 2 - 1; } - if(details.childId >= 131 && details.childId <= 159) { - selectedIndex = ((details.childId - 129)/2 -1) + 15; + if (details.childId >= 131 && details.childId <= 159) { + selectedIndex = (details.childId - 129) / 2 - 1 + 15; } - if(selectedIndex != undefined) { - let teleportIndex = selectedIndex + (30 * (playerWidget.metadata.page-1)); - if(!details.player.savedMetadata.lastTravel) { + if (selectedIndex != undefined) { + let teleportIndex = selectedIndex + 30 * (playerWidget.metadata.page - 1); + if (!details.player.savedMetadata.lastTravel) { details.player.savedMetadata.lastTravel = new Array(10); } - if(teleportIndex < INTRO_PAGE_COUNT * ITEMS_PER_PAGE) { - if(teleportIndex < 3 && teleportIndex > 12) { - openTravel(details.player, playerWidget.metadata.page) + if (teleportIndex < INTRO_PAGE_COUNT * ITEMS_PER_PAGE) { + if (teleportIndex < 3 && teleportIndex > 12) { + openTravel(details.player, playerWidget.metadata.page); } - teleportIndex = details.player.savedMetadata.lastTravel[teleportIndex - 3] - if(!teleportIndex) { - openTravel(details.player, playerWidget.metadata.page) + teleportIndex = details.player.savedMetadata.lastTravel[teleportIndex - 3]; + if (!teleportIndex) { + openTravel(details.player, playerWidget.metadata.page); } } else { - teleportIndex = teleportIndex - INTRO_PAGE_COUNT * ITEMS_PER_PAGE + teleportIndex = teleportIndex - INTRO_PAGE_COUNT * ITEMS_PER_PAGE; } - const newTravelLog = [teleportIndex, ...details.player.savedMetadata.lastTravel.slice(0, 9)] + const newTravelLog = [teleportIndex, ...details.player.savedMetadata.lastTravel.slice(0, 9)]; for (let index = 1; newTravelLog.length; index++) { const element = newTravelLog[index]; if (element === teleportIndex) { - newTravelLog[index] = newTravelLog[index+1] + newTravelLog[index] = newTravelLog[index + 1]; } - if(element === undefined) { + if (element === undefined) { if (newTravelLog[index + 1] === undefined) { break; } - newTravelLog[index] = newTravelLog[index+1]; + newTravelLog[index] = newTravelLog[index + 1]; } } details.player.savedMetadata.lastTravel = newTravelLog; + details.player.teleport(activeWorld.travelLocations.locations[teleportIndex].position); - details.player.teleport(activeWorld.travelLocations.locations[teleportIndex].position) - - details.player.interfaceState.closeAllSlots() + details.player.interfaceState.closeAllSlots(); } else { - openTravel(details.player, playerWidget.metadata.page) + openTravel(details.player, playerWidget.metadata.page); } -} +}; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts index 159f3d17e..8c2647fe3 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts @@ -1,8 +1,7 @@ import type { commandActionHandler } from '@engine/action/pipe/player-command.action'; - -const spawnPotato: commandActionHandler = (details) => { - details.player.giveItem('rs:rotten_potato') +const spawnPotato: commandActionHandler = details => { + details.player.giveItem('rs:rotten_potato'); }; export default spawnPotato; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts index af1370cde..81e0eec1e 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts @@ -6,32 +6,29 @@ enum DialogueOption { WIPE_INVENTORY, SETUP_POH, TELEPORT_TO_PLAYER, - SPAWN_AGGRESSIVE_NPC + SPAWN_AGGRESSIVE_NPC, } -const eatPotato: itemInteractionActionHandler = async (details) => { - +const eatPotato: itemInteractionActionHandler = async details => { let chosenOption: DialogueOption; - await dialogue([details.player], [ - options => [ - `Set all stats`, [ - execute(() => chosenOption = DialogueOption.SET_ALL_STATS) - ], - `Wipe inventory`, [ - execute(() => chosenOption = DialogueOption.WIPE_INVENTORY) - ], - `Setup POH`, [ - execute(() => chosenOption = DialogueOption.SETUP_POH) + await dialogue( + [details.player], + [ + options => [ + `Set all stats`, + [execute(() => (chosenOption = DialogueOption.SET_ALL_STATS))], + `Wipe inventory`, + [execute(() => (chosenOption = DialogueOption.WIPE_INVENTORY))], + `Setup POH`, + [execute(() => (chosenOption = DialogueOption.SETUP_POH))], + `Teleport to player`, + [execute(() => (chosenOption = DialogueOption.TELEPORT_TO_PLAYER))], + `Spawn aggressive NPC`, + [execute(() => (chosenOption = DialogueOption.SPAWN_AGGRESSIVE_NPC))], ], - `Teleport to player`, [ - execute(() => chosenOption = DialogueOption.TELEPORT_TO_PLAYER) - ], - `Spawn aggressive NPC`, [ - execute(() => chosenOption = DialogueOption.SPAWN_AGGRESSIVE_NPC) - ], - ] - ]); + ], + ); switch (chosenOption!) { case DialogueOption.SET_ALL_STATS: @@ -41,7 +38,6 @@ const eatPotato: itemInteractionActionHandler = async (details) => { default: break; } - }; export default eatPotato; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts index c9c3479fd..5abe82b80 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts @@ -1,8 +1,8 @@ -import { RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; -import { findItem } from '@engine/config/config-handler'; import type { itemOnItemActionHandler } from '@engine/action/pipe/item-on-item.action'; +import { findItem } from '@engine/config/config-handler'; +import { RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; -const itemOnPotato: itemOnItemActionHandler = (details) => { +const itemOnPotato: itemOnItemActionHandler = details => { const slotToDelete = details.usedItem.itemId === RottenPotatoItem.gameId ? details.usedWithSlot : details.usedSlot; const inventoryItem = details.player.inventory.items[slotToDelete]; @@ -15,7 +15,7 @@ const itemOnPotato: itemOnItemActionHandler = (details) => { const item = inventoryItem.itemId; const itemDetails = findItem(item); details.player.removeItem(slotToDelete); - details.player.sendLogMessage(`Whee... ${itemDetails?.name || 'Unknown item'} All gone!`, false) + details.player.sendLogMessage(`Whee... ${itemDetails?.name || 'Unknown item'} All gone!`, false); }; export default itemOnPotato; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts index 96b03614c..4a5cf6811 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts @@ -5,36 +5,31 @@ import type { Player } from '@engine/world/actor/player/player'; import type { Item } from '@engine/world/items/item'; import { logger } from '@runejs/common'; -export const potatoOnPlayer: itemOnPlayerActionHandler = (details) => { +export const potatoOnPlayer: itemOnPlayerActionHandler = details => { const widget = details.player.interfaceState.openWidget(widgets.bank.depositBoxWidget.widgetId, { slot: 'screen', - fakeWidget: 3100001 + fakeWidget: 3100001, }); widget.metadata['player'] = details.otherPlayer; details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.depositBoxWidget, details.otherPlayer.inventory); - details.player.modifyWidget(widgets.bank.depositBoxWidget.widgetId, { childId: widgets.bank.depositBoxWidget.titleText, - text: `${details.otherPlayer.username}'s Inventory` - }) - - - + text: `${details.otherPlayer.username}'s Inventory`, + }); }; -export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (details) => { +export const potatoManipulatePlayerInventory: itemInteractionActionHandler = details => { const playerWidget = details.player.interfaceState.findWidget(widgets.bank.depositBoxWidget.widgetId); - if(!playerWidget) { + if (!playerWidget) { return; } const otherPlayer: Player = playerWidget.metadata['player']; - if(!otherPlayer) { + if (!otherPlayer) { return; } - // If the item is a noted item, we need to de-note it const itemIdToAdd: number = details.itemId; @@ -47,7 +42,7 @@ export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (de const slotsWithItem = otherPlayer.inventory.findAll(details.itemId); let itemAmount = 0; - slotsWithItem.forEach((slot) => { + slotsWithItem.forEach(slot => { const item = otherPlayer.inventory.items[slot]; if (!item) { @@ -95,5 +90,4 @@ export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (de details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.depositBoxWidget, otherPlayer.inventory); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); otherPlayer.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, otherPlayer.inventory); - }; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts index e38fb9dd1..8dcb89dab 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts @@ -1,16 +1,16 @@ -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; -import type { Player } from '@engine/world/actor/player/player'; -import { dialogue, execute } from '@engine/world/actor/dialogue'; +import { getActionHooks } from '@engine/action/hook/action-hook'; import { advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import type { ObjectInteractionActionHook } from '@engine/action/pipe/object-interaction.action'; +import { dialogue, execute } from '@engine/world/actor/dialogue'; +import type { Player } from '@engine/world/actor/player/player'; import { objectIds } from '@engine/world/config/object-ids'; import { openTravel } from '@plugins/items/rotten-potato/helpers/rotten-potato-travel'; -import { getActionHooks } from '@engine/action/hook/action-hook'; - function openBank(player: Player) { - const interactionActions = getActionHooks('object_interaction') - .filter(plugin => advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly')); + const interactionActions = getActionHooks('object_interaction').filter(plugin => + advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly'), + ); interactionActions.forEach(plugin => { if (!plugin.handler) { return; @@ -24,13 +24,13 @@ function openBank(player: Player) { x: player.position.x, y: player.position.y, orientation: 0, - type: 0 + type: 0, }, option: 'use-quickly', position: player.position, objectConfig: undefined as any, - cacheOriginal: undefined as any - }) + cacheOriginal: undefined as any, + }); }); } @@ -38,29 +38,29 @@ enum DialogueOption { BANK, TELEPORT_MENU, TELEPORT_TO_RARE_DROP, - FORCE_RARE_DROP + FORCE_RARE_DROP, } -const peelPotato: itemInteractionActionHandler = async (details) => { - +const peelPotato: itemInteractionActionHandler = async details => { let chosenOption: DialogueOption; // console.log(world.travelLocations.locations) - await dialogue([details.player], [ - options => [ - `Bank menu`, [ - execute(() => chosenOption = DialogueOption.BANK) - ], - `Travel Far!`, [ - execute(() => chosenOption = DialogueOption.TELEPORT_MENU) + await dialogue( + [details.player], + [ + options => [ + `Bank menu`, + [execute(() => (chosenOption = DialogueOption.BANK))], + `Travel Far!`, + [execute(() => (chosenOption = DialogueOption.TELEPORT_MENU))], + // `Teleport to RARE!`, [ + // execute(() => chosenOption = DialogueOption.TELEPORT_TO_RARE_DROP) + // ], + // `Spawn RARE!`, [ + // execute(() => chosenOption = DialogueOption.FORCE_RARE_DROP) + // ], ], - // `Teleport to RARE!`, [ - // execute(() => chosenOption = DialogueOption.TELEPORT_TO_RARE_DROP) - // ], - // `Spawn RARE!`, [ - // execute(() => chosenOption = DialogueOption.FORCE_RARE_DROP) - // ], - ] - ]); + ], + ); // using ! here because we have just set it in the dialogue switch (chosenOption!) { @@ -73,7 +73,6 @@ const peelPotato: itemInteractionActionHandler = async (details) => { default: break; } - }; export default peelPotato; diff --git a/src/plugins/items/rotten-potato/rotten-potato.plugin.ts b/src/plugins/items/rotten-potato/rotten-potato.plugin.ts index dda439f95..602d2309e 100644 --- a/src/plugins/items/rotten-potato/rotten-potato.plugin.ts +++ b/src/plugins/items/rotten-potato/rotten-potato.plugin.ts @@ -1,12 +1,12 @@ +import type { WidgetInteractionActionHook } from '@engine/action/pipe/widget-interaction.action'; import { widgets } from '@engine/config/config-handler'; +import { ExecuteIfAdmin, RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; +import { travelMenuInteract } from '@plugins/items/rotten-potato/helpers/rotten-potato-travel'; import spawnPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-command-hook'; +import eatPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-eat'; import itemOnPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-item-on-item'; -import { ExecuteIfAdmin, RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; +import { potatoManipulatePlayerInventory, potatoOnPlayer } from '@plugins/items/rotten-potato/hooks/rotten-potato-item-on-player'; import peelPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-peel'; -import { potatoOnPlayer, potatoManipulatePlayerInventory } from '@plugins/items/rotten-potato/hooks/rotten-potato-item-on-player'; -import eatPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-eat'; -import { travelMenuInteract } from '@plugins/items/rotten-potato/helpers/rotten-potato-travel'; -import type { WidgetInteractionActionHook } from '@engine/action/pipe/widget-interaction.action'; export default { pluginId: 'promises:rotten-potato', @@ -16,46 +16,46 @@ export default { widgets: widgets.inventory, itemIds: RottenPotatoItem.gameId, options: 'peel', - handler: (details) => ExecuteIfAdmin(details, peelPotato), - cancelOtherActions: true + handler: details => ExecuteIfAdmin(details, peelPotato), + cancelOtherActions: true, }, { type: 'item_interaction', widgets: widgets.inventory, itemIds: RottenPotatoItem.gameId, options: 'eat', - handler: (details) => ExecuteIfAdmin(details, eatPotato), - cancelOtherActions: true + handler: details => ExecuteIfAdmin(details, eatPotato), + cancelOtherActions: true, }, { type: 'item_on_player', itemIds: RottenPotatoItem.gameId, - handler: (details) => ExecuteIfAdmin(details, potatoOnPlayer), - walkTo: false + handler: details => ExecuteIfAdmin(details, potatoOnPlayer), + walkTo: false, }, { type: 'player_command', - commands: [ 'potato' ], - handler: (details) => ExecuteIfAdmin(details, spawnPotato), - cancelOtherActions: true + commands: ['potato'], + handler: details => ExecuteIfAdmin(details, spawnPotato), + cancelOtherActions: true, }, { type: 'item_on_item', items: [{ item1: RottenPotatoItem.gameId }], - handler: (details) => ExecuteIfAdmin(details, itemOnPotato), - cancelOtherActions: true + handler: details => ExecuteIfAdmin(details, itemOnPotato), + cancelOtherActions: true, }, { type: 'item_interaction', widgets: { ...widgets.bank.depositBoxWidget, widgetId: 3100001 }, - options: [ 'deposit-1', 'deposit-5', 'deposit-10', 'deposit-all' ], - handler: (details) => ExecuteIfAdmin(details, potatoManipulatePlayerInventory), + options: ['deposit-1', 'deposit-5', 'deposit-10', 'deposit-all'], + handler: details => ExecuteIfAdmin(details, potatoManipulatePlayerInventory), }, { type: 'widget_interaction', widgetIds: 3100002, - handler: (details) => ExecuteIfAdmin(details, travelMenuInteract), - multi: true - } as WidgetInteractionActionHook - ] + handler: details => ExecuteIfAdmin(details, travelMenuInteract), + multi: true, + } as WidgetInteractionActionHook, + ], }; diff --git a/src/plugins/items/runecrafting/tiaras.plugin.ts b/src/plugins/items/runecrafting/tiaras.plugin.ts index 0801df9f7..2f43eca34 100644 --- a/src/plugins/items/runecrafting/tiaras.plugin.ts +++ b/src/plugins/items/runecrafting/tiaras.plugin.ts @@ -1,10 +1,10 @@ import type { equipmentChangeActionHandler } from '@engine/action/pipe/equipment-change.action'; -export const equip: equipmentChangeActionHandler = (details) => { +export const equip: equipmentChangeActionHandler = details => { const { player } = details; player.outgoingPackets.updateClientConfig(491, 1); }; -export const unequip: equipmentChangeActionHandler = (details) => { +export const unequip: equipmentChangeActionHandler = details => { const { player } = details; player.outgoingPackets.updateClientConfig(491, 0); }; @@ -16,12 +16,13 @@ export default { type: 'equipment_change', eventType: 'equip', handler: equip, - itemIds: 5527 - }, { + itemIds: 5527, + }, + { type: 'equipment_change', eventType: 'unequip', handler: unequip, - itemIds: 5527 - } - ] + itemIds: 5527, + }, + ], }; diff --git a/src/plugins/items/shopping/buy-from-shop.plugin.ts b/src/plugins/items/shopping/buy-from-shop.plugin.ts index 4e7abe30e..1ea9319f6 100644 --- a/src/plugins/items/shopping/buy-from-shop.plugin.ts +++ b/src/plugins/items/shopping/buy-from-shop.plugin.ts @@ -1,10 +1,10 @@ +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { findItem, findShop, widgets } from '@engine/config/config-handler'; +import { itemIds } from '@engine/world/config/item-ids'; import type { Item } from '@engine/world/items/item'; import type { ItemContainer } from '@engine/world/items/item-container'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { itemIds } from '@engine/world/config/item-ids'; -import { findItem, findShop, widgets } from '@engine/config/config-handler'; import { logger } from '@runejs/common'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; function removeCoins(inventory: ItemContainer, coinsIndex: number, cost: number): void { const coins = inventory.items[coinsIndex]; @@ -18,32 +18,32 @@ function removeCoins(inventory: ItemContainer, coinsIndex: number, cost: number) inventory.set(coinsIndex, { itemId: itemIds.coins, amount: amountAfterPurchase }); } -export const handler: itemInteractionActionHandler = (details) => { +export const handler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, widgetId, option } = details; - if(!player.interfaceState.findWidget(widgetId)) { + if (!player.interfaceState.findWidget(widgetId)) { return; } const openedShopKey = player.metadata.lastOpenedShopKey; - if(!openedShopKey) { + if (!openedShopKey) { return; } const shop = findShop(openedShopKey); - if(!shop) { + if (!shop) { return; } const shopContainer = shop.container; const shopItem = getItemFromContainer(itemId, itemSlot, shopContainer); - if(!shopItem) { + if (!shopItem) { // The specified item was not found in the specified slot. return; } - if(shopItem.amount <= 0) { + if (shopItem.amount <= 0) { // Out of stock return; } @@ -51,35 +51,35 @@ export const handler: itemInteractionActionHandler = (details) => { const buyAmounts = { 'buy-1': 1, 'buy-5': 5, - 'buy-10': 10 + 'buy-10': 10, }; let buyAmount = buyAmounts[option]; - if(shopItem.amount < buyAmount) { + if (shopItem.amount < buyAmount) { buyAmount = shopItem.amount; } const buyItem = findItem(itemId); - if(!buyItem) { + if (!buyItem) { logger.error(`Could not find cache item for item id ${itemId} in shop ${openedShopKey}`); return; } const buyItemValue = shop.getBuyFromShopPrice(buyItem); - player.sendMessage(`${buyItem.key} : ${buyItemValue}, ${buyItem.value}`) + player.sendMessage(`${buyItem.key} : ${buyItemValue}, ${buyItem.value}`); let buyCost = buyAmount * buyItemValue; const coinsIndex = player.hasCoins(buyCost); - if(coinsIndex === -1) { + if (coinsIndex === -1) { player.sendMessage(`You don't have enough coins.`); return; } const inventory = player.inventory; - if(buyItem.stackable) { + if (buyItem.stackable) { const inventoryStackSlot = inventory.items.findIndex(item => itemId === itemId); - if(inventoryStackSlot === -1) { - if(inventory.getFirstOpenSlot() === -1) { + if (inventoryStackSlot === -1) { + if (inventory.getFirstOpenSlot() === -1) { player.sendMessage(`You don't have enough space in your inventory.`); return; } @@ -87,11 +87,13 @@ export const handler: itemInteractionActionHandler = (details) => { const inventoryItem = inventory.items[inventoryStackSlot]; if (!inventoryItem) { - logger.error(`Coult not find inventory item at slot ${inventoryStackSlot} for player ${player.username} while trying to stack`); + logger.error( + `Coult not find inventory item at slot ${inventoryStackSlot} for player ${player.username} while trying to stack`, + ); return; } - if(inventoryItem.amount + buyAmount >= 2147483647) { + if (inventoryItem.amount + buyAmount >= 2147483647) { player.sendMessage(`You don't have enough space in your inventory.`); return; } @@ -100,7 +102,8 @@ export const handler: itemInteractionActionHandler = (details) => { removeCoins(inventory, coinsIndex, buyCost); const item: Item = { - itemId, amount: inventoryItem.amount + buyAmount + itemId, + amount: inventoryItem.amount + buyAmount, }; inventory.set(inventoryStackSlot, item); @@ -108,15 +111,15 @@ export const handler: itemInteractionActionHandler = (details) => { } else { let bought = 0; - for(let i = 0; i < buyAmount; i++) { - if(inventory.add({ itemId, amount: 1 }) !== null) { + for (let i = 0; i < buyAmount; i++) { + if (inventory.add({ itemId, amount: 1 }) !== null) { bought++; } else { break; } } - if(bought !== buyAmount) { + if (bought !== buyAmount) { player.sendMessage(`You don't have enough space in your inventory.`); } @@ -136,9 +139,9 @@ export default { { type: 'item_interaction', widgets: widgets.shop, - options: [ 'buy-1', 'buy-5', 'buy-10' ], + options: ['buy-1', 'buy-5', 'buy-10'], handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/shopping/item-value.plugin.ts b/src/plugins/items/shopping/item-value.plugin.ts index 8ddd12b66..1194190c5 100644 --- a/src/plugins/items/shopping/item-value.plugin.ts +++ b/src/plugins/items/shopping/item-value.plugin.ts @@ -2,20 +2,20 @@ import type { itemInteractionActionHandler } from '@engine/action/pipe/item-inte import { findItem, findShop, widgets } from '@engine/config/config-handler'; import { getItemFromContainer } from '@engine/world/items/item-container'; -export const shopSellValueHandler: itemInteractionActionHandler = (details) => { +export const shopSellValueHandler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, widgetId, option } = details; - if(!player.interfaceState.findWidget(widgetId)) { + if (!player.interfaceState.findWidget(widgetId)) { return; } const openedShopKey = player.metadata.lastOpenedShopKey; - if(!openedShopKey) { + if (!openedShopKey) { return; } const shop = findShop(openedShopKey); - if(!shop) { + if (!shop) { return; } @@ -23,19 +23,19 @@ export const shopSellValueHandler: itemInteractionActionHandler = (details) => { const shopItem = getItemFromContainer(itemId, itemSlot, shopContainer); console.log(itemId, itemSlot, openedShopKey, shopContainer); - if(!shopItem) { + if (!shopItem) { // The specified item was not found in the specified slot. player.sendMessage(`ERROR item not in shopslot.`); return; } - if(shopItem.amount <= 0) { + if (shopItem.amount <= 0) { player.sendMessage(`The shop has ran out of stock.`); // Out of stock return; } const buyItem = findItem(itemId); - if(!buyItem) { + if (!buyItem) { // The specified item was not found in the specified slot. player.sendMessage(`Error item does not exist. [id:${itemId}]`); return; @@ -45,21 +45,21 @@ export const shopSellValueHandler: itemInteractionActionHandler = (details) => { export const shopPurchaseValueHandler: itemInteractionActionHandler = ({ player, itemDetails }) => { const openedShopKey = player.metadata.lastOpenedShopKey; - if(!openedShopKey) { + if (!openedShopKey) { return; } const shop = findShop(openedShopKey); - if(!shop) { + if (!shop) { return; } const shopBuyPrice = shop.getBuyFromShopPrice(itemDetails); - if(shopBuyPrice === -1) { + if (shopBuyPrice === -1) { player.sendMessage(`You can't sell this item to this shop.`); } else { - player.sendMessage(`${ itemDetails.name }: shop will buy for ${ shopBuyPrice } coins.`); + player.sendMessage(`${itemDetails.name}: shop will buy for ${shopBuyPrice} coins.`); } }; @@ -71,13 +71,14 @@ export default { widgets: widgets.shop, options: 'value', handler: shopSellValueHandler, - cancelOtherActions: false - }, { + cancelOtherActions: false, + }, + { type: 'item_interaction', widgets: widgets.shopPlayerInventory, options: 'value', handler: shopPurchaseValueHandler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/shopping/sell-to-shop.plugin.ts b/src/plugins/items/shopping/sell-to-shop.plugin.ts index f4266dc9d..f2dccf00d 100644 --- a/src/plugins/items/shopping/sell-to-shop.plugin.ts +++ b/src/plugins/items/shopping/sell-to-shop.plugin.ts @@ -1,30 +1,29 @@ +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { findShop, widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { findShop, widgets } from '@engine/config/config-handler'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; - -export const handler: itemInteractionActionHandler = (details) => { +export const handler: itemInteractionActionHandler = details => { const { player, itemId, itemSlot, option, itemDetails } = details; - if(!player.interfaceState.findWidget(widgets.shop.widgetId)) { + if (!player.interfaceState.findWidget(widgets.shop.widgetId)) { return; } const openedShopKey = player.metadata.lastOpenedShopKey; - if(!openedShopKey) { + if (!openedShopKey) { return; } const shop = findShop(openedShopKey); - if(!shop) { + if (!shop) { return; } const inventory = player.inventory; const inventoryItem = getItemFromContainer(itemId, itemSlot, inventory); - if(!inventoryItem) { + if (!inventoryItem) { // The specified item was not found in the specified slot. return; } @@ -32,34 +31,34 @@ export const handler: itemInteractionActionHandler = (details) => { const sellAmounts = { 'sell-1': 1, 'sell-5': 5, - 'sell-10': 10 + 'sell-10': 10, }; let sellAmount = sellAmounts[option]; const shopContainer = shop.container; const shopSpaces = shopContainer.items.filter(item => item === null); const shopItemIndex = shopContainer.items.findIndex(item => item !== null && item.itemId === itemId); - if(shopItemIndex === -1 && shopSpaces.length === 0) { + if (shopItemIndex === -1 && shopSpaces.length === 0) { player.sendMessage(`There isn't enough space in the shop.`); return; } const shopItem = shopContainer.items[shopItemIndex]; - if(itemDetails.stackable) { - if(inventoryItem.amount < sellAmount) { + if (itemDetails.stackable) { + if (inventoryItem.amount < sellAmount) { inventory.remove(itemSlot); sellAmount = inventoryItem.amount; } else { inventory.set(itemSlot, { itemId, amount: inventoryItem.amount - sellAmount }); } } else { - const foundItems = inventory.items.map((item, i) => item !== null && item.itemId === itemId ? i : null).filter(i => i !== null); - if(foundItems.length < sellAmount) { + const foundItems = inventory.items.map((item, i) => (item !== null && item.itemId === itemId ? i : null)).filter(i => i !== null); + if (foundItems.length < sellAmount) { sellAmount = foundItems.length; } - for(let i = 0; i < sellAmount; i++) { + for (let i = 0; i < sellAmount; i++) { const item = foundItems[i]; if (!item) { @@ -72,17 +71,17 @@ export const handler: itemInteractionActionHandler = (details) => { const itemValue = shop.getSellToShopPrice(itemDetails); // @TODO scale price per item, not per sale - if(!shopItem) { + if (!shopItem) { shopContainer.set(shopContainer.getFirstOpenSlot(), { itemId, amount: sellAmount }); } else { shopItem.amount += sellAmount; } const sellPrice = sellAmount * itemValue; // @TODO scale price per item, not per sale - if(sellPrice > 0) { + if (sellPrice > 0) { let coinsIndex = player.hasCoins(1); - if(coinsIndex === -1) { + if (coinsIndex === -1) { coinsIndex = inventory.getFirstOpenSlot(); inventory.set(coinsIndex, { itemId: itemIds.coins, amount: sellPrice }); } else { @@ -102,9 +101,9 @@ export default { { type: 'item_interaction', widgets: widgets.shopPlayerInventory, - options: [ 'sell-1', 'sell-5', 'sell-10' ], + options: ['sell-1', 'sell-5', 'sell-10'], handler, - cancelOtherActions: false - } - ] + cancelOtherActions: false, + }, + ], }; diff --git a/src/plugins/items/swap-items.plugin.ts b/src/plugins/items/swap-items.plugin.ts index 6a827628f..c36fb8f47 100644 --- a/src/plugins/items/swap-items.plugin.ts +++ b/src/plugins/items/swap-items.plugin.ts @@ -1,30 +1,30 @@ -import type { ItemContainer } from '@engine/world/items/item-container'; -import type { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config/config-handler'; import type { itemSwapActionHandler } from '@engine/action/pipe/item-swap.action'; +import { widgets } from '@engine/config/config-handler'; +import type { Player } from '@engine/world/actor/player/player'; +import type { ItemContainer } from '@engine/world/items/item-container'; -type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; +type WidgetDetail = [number, number, (player: Player) => ItemContainer]; const swappableWidgets: WidgetDetail[] = [ // Player Inventory - [ widgets.inventory.widgetId, widgets.inventory.containerId, player => player.inventory ], + [widgets.inventory.widgetId, widgets.inventory.containerId, player => player.inventory], // Player Bank Screen - [ widgets.bank.screenWidget.widgetId, widgets.bank.screenWidget.containerId, player => player.bank ] + [widgets.bank.screenWidget.widgetId, widgets.bank.screenWidget.containerId, player => player.bank], ]; function swapItems(container: ItemContainer, fromSlot: number, toSlot: number): void { - if(toSlot > container.size - 1 || fromSlot > container.size - 1) { + if (toSlot > container.size - 1 || fromSlot > container.size - 1) { return; } container.swap(fromSlot, toSlot); } -export const action: itemSwapActionHandler = (details) => { +export const action: itemSwapActionHandler = details => { const { player, widgetId, containerId, fromSlot, toSlot } = details; const widgetDetails = swappableWidgets.filter(widgetDetail => widgetDetail[0] === widgetId && widgetDetail[1] === containerId); - if(widgetDetails && widgetDetails[0]) { + if (widgetDetails && widgetDetails[0]) { const itemContainer: ItemContainer = widgetDetails[0][2](player); swapItems(itemContainer, fromSlot, toSlot); } @@ -36,7 +36,7 @@ export default { { type: 'item_swap', widgetIds: swappableWidgets.map(widgetDetails => widgetDetails[0]), - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/music/music-regions.plugin.ts b/src/plugins/music/music-regions.plugin.ts index ecb32a4d9..05819f3cf 100644 --- a/src/plugins/music/music-regions.plugin.ts +++ b/src/plugins/music/music-regions.plugin.ts @@ -3,23 +3,21 @@ import { findMusicTrack, findSongIdByRegionId, musicRegionMap, musicRegions, wid import { colors } from '@engine/util/colors'; import { MusicPlayerMode } from '@engine/world/sound/music'; - musicRegions.forEach(song => song.regionIds.forEach(region => musicRegionMap.set(region, song.songId))); function getByValue(map, searchValue) { for (const [key, value] of map.entries()) { - if (value === searchValue) - return key; + if (value === searchValue) return key; } } const regionChangedHandler = ({ player, currentMapRegionId }): void => { const songId = findSongIdByRegionId(currentMapRegionId); - if(songId == null) { + if (songId == null) { return; } - const musicTrack = findMusicTrack(songId) + const musicTrack = findMusicTrack(songId); if (!musicTrack) { return; @@ -27,30 +25,32 @@ const regionChangedHandler = ({ player, currentMapRegionId }): void => { const songName = musicTrack.songName; // player.sendMessage(`Playing ${songId}:${getByValue(songs, songId)} at region ${currentMapRegionId}`); - if(!player.musicTracks.includes(songId)) { + if (!player.musicTracks.includes(songId)) { player.musicTracks.push(songId); player.sendMessage('You have unlocked a new music track: ' + songName + '.'); - player.modifyWidget(widgets.musicPlayerTab, { childId: musicTrack.musicTabButtonId, textColor: colors.green }); + player.modifyWidget(widgets.musicPlayerTab, { childId: musicTrack.musicTabButtonId, textColor: colors.green }); } - if(player.settings.musicPlayerMode === MusicPlayerMode.AUTO) { + if (player.settings.musicPlayerMode === MusicPlayerMode.AUTO) { player.playSong(songId); } }; const playerInitHandler: playerInitActionHandler = ({ player }): void => { // Plays the appropriate location's song on player init - regionChangedHandler({ player, - currentMapRegionId: ((player.position.x >> 6) << 8) + (player.position.y >> 6) }); + regionChangedHandler({ player, currentMapRegionId: ((player.position.x >> 6) << 8) + (player.position.y >> 6) }); }; export default { pluginId: 'rs:music_regions', - hooks: [{ - type: 'region_change', - regionType: 'region', - handler: regionChangedHandler - }, { - type: 'player_init', - handler: playerInitHandler - }] + hooks: [ + { + type: 'region_change', + regionType: 'region', + handler: regionChangedHandler, + }, + { + type: 'player_init', + handler: playerInitHandler, + }, + ], }; diff --git a/src/plugins/music/music-tab.plugin.ts b/src/plugins/music/music-tab.plugin.ts index 4516d7fba..c410d2a71 100644 --- a/src/plugins/music/music-tab.plugin.ts +++ b/src/plugins/music/music-tab.plugin.ts @@ -1,47 +1,44 @@ import type { buttonActionHandler } from '@engine/action/pipe/button.action'; -import { findSongIdByRegionId, findMusicTrackByButtonId, widgets } from '@engine/config/config-handler'; +import { findMusicTrackByButtonId, findSongIdByRegionId, widgets } from '@engine/config/config-handler'; import { activeWorld } from '@engine/world'; import { widgetScripts } from '@engine/world/config/widget'; -import { MusicTabButtonIds, MusicPlayerMode } from '@engine/world/sound/music'; +import { MusicPlayerMode, MusicTabButtonIds } from '@engine/world/sound/music'; import { logger } from '@runejs/common'; -export const handler: buttonActionHandler = (details) => { +export const handler: buttonActionHandler = details => { const { player, buttonId } = details; - if(buttonId === MusicTabButtonIds.AUTO_BUTTON_ID) { + if (buttonId === MusicTabButtonIds.AUTO_BUTTON_ID) { player.settings.musicPlayerMode = MusicPlayerMode.AUTO; - const songIdForCurrentRegion = findSongIdByRegionId( - activeWorld.chunkManager.getRegionIdForWorldPosition(player.position)); + const songIdForCurrentRegion = findSongIdByRegionId(activeWorld.chunkManager.getRegionIdForWorldPosition(player.position)); if (!songIdForCurrentRegion) { logger.warn(`No song found for current region`); return; } - if(player.savedMetadata['currentSongIdPlaying'] !== songIdForCurrentRegion) { + if (player.savedMetadata['currentSongIdPlaying'] !== songIdForCurrentRegion) { player.playSong(songIdForCurrentRegion); } - } else if(buttonId === MusicTabButtonIds.MANUAL_BUTTON_ID) { + } else if (buttonId === MusicTabButtonIds.MANUAL_BUTTON_ID) { player.settings.musicPlayerMode = MusicPlayerMode.MANUAL; - } else if(buttonId === MusicTabButtonIds.LOOP_BUTTON_ID) { + } else if (buttonId === MusicTabButtonIds.LOOP_BUTTON_ID) { player.settings.musicPlayerLoopMode ^= 1; } const musicTrack = findMusicTrackByButtonId(buttonId); - if(musicTrack === null) { + if (musicTrack === null) { return; - } else if(player.musicTracks.includes(musicTrack.songId)) { + } else if (player.musicTracks.includes(musicTrack.songId)) { player.playSong(musicTrack.songId); player.settings.musicPlayerMode = MusicPlayerMode.MANUAL; player.outgoingPackets.updateClientConfig(widgetScripts.musicPlayerAutoManual, 0); } else { - player.sendMessage('You haven\'t unlocked this piece of music yet!'); + player.sendMessage("You haven't unlocked this piece of music yet!"); } }; export default { pluginId: 'rs:music_tab', - hooks: [ - { type: 'button', widgetId: widgets.musicPlayerTab, handler } - ] + hooks: [{ type: 'button', widgetId: widgets.musicPlayerTab, handler }], }; diff --git a/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts b/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts index 4fd483a86..68652b427 100644 --- a/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts +++ b/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts @@ -1,32 +1,34 @@ -import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; -import { findShop } from '@engine/config/config-handler'; import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; +import { findShop } from '@engine/config/config-handler'; +import { DialogueEmote, dialogueAction } from '@engine/world/actor/player/dialogue-action'; +const tradeAction: npcInteractionActionHandler = ({ player }) => findShop('rs:dommiks_crafting_store')?.open(player); -const tradeAction: npcInteractionActionHandler = ({ player }) => - findShop('rs:dommiks_crafting_store')?.open(player); - -const talkToAction : npcInteractionActionHandler = (details) => { +const talkToAction: npcInteractionActionHandler = details => { const { player, npc } = details; dialogueAction(player) .then(async d => d.npc(npc, DialogueEmote.CALM_TALK_1, ['Would you like to buy some crafting equipment?'])) - .then(async d => d.options('Would you like to buy some crafting equipment?', ['No thanks. I\'ve got all the Crafting equipment I need.', 'Let\'s see what you\'ve got, then.'])) + .then(async d => + d.options('Would you like to buy some crafting equipment?', [ + "No thanks. I've got all the Crafting equipment I need.", + "Let's see what you've got, then.", + ]), + ) .then(async d => { switch (d.action) { case 1: - return d.player(DialogueEmote.JOYFUL, [ 'No thanks; I\'ve got all the Crafting equipment I need.' ]) + return d + .player(DialogueEmote.JOYFUL, ["No thanks; I've got all the Crafting equipment I need."]) .then(async d => d.npc(npc, DialogueEmote.CALM_TALK_2, ['Okay. Fare well on your travels.'])) .then(d => { d.close(); return d; }); case 2: - return d.player(DialogueEmote.CALM_TALK_1, ['No, thank you.']) - .then(d => { - tradeAction(details); - return d; - }); - + return d.player(DialogueEmote.CALM_TALK_1, ['No, thank you.']).then(d => { + tradeAction(details); + return d; + }); } }); }; @@ -35,6 +37,6 @@ export default { pluginId: 'rs:dommik_crafting_shop', hooks: [ { type: 'npc_interaction', npcs: 'rs:alkharid_dommik', options: 'trade', walkTo: true, handler: tradeAction }, - { type: 'npc_interaction', npcs: 'rs:alkharid_dommik', options: 'talk-to', walkTo: true, handler: talkToAction } - ] + { type: 'npc_interaction', npcs: 'rs:alkharid_dommik', options: 'talk-to', walkTo: true, handler: talkToAction }, + ], }; diff --git a/src/plugins/npcs/al-kharid/gem-trader.plugin.ts b/src/plugins/npcs/al-kharid/gem-trader.plugin.ts index d47b65c8a..ebd3fa5cc 100644 --- a/src/plugins/npcs/al-kharid/gem-trader.plugin.ts +++ b/src/plugins/npcs/al-kharid/gem-trader.plugin.ts @@ -1,32 +1,31 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; import { findShop } from '@engine/config/config-handler'; +import { DialogueEmote, dialogueAction } from '@engine/world/actor/player/dialogue-action'; +const tradeAction: npcInteractionActionHandler = ({ player }) => findShop('rs:alkharid_gem_trader')?.open(player); -const tradeAction: npcInteractionActionHandler = ({ player }) => - findShop('rs:alkharid_gem_trader')?.open(player); - -const talkToAction : npcInteractionActionHandler = (details) => { +const talkToAction: npcInteractionActionHandler = details => { const { player, npc } = details; dialogueAction(player) - .then(async d => d.npc(npc, DialogueEmote.CALM_TALK_1, [ 'Good day to you, traveller.', 'Would you be interested in buying some gems?'])) + .then(async d => + d.npc(npc, DialogueEmote.CALM_TALK_1, ['Good day to you, traveller.', 'Would you be interested in buying some gems?']), + ) .then(async d => d.options('Would you be interested in buying some gems?', ['Yes, please.', 'No, thank you.'])) .then(async d => { switch (d.action) { case 1: - return d.player(DialogueEmote.JOYFUL, [ 'Yes, please!' ]) - .then(d => { - tradeAction(details); - return d; - }); + return d.player(DialogueEmote.JOYFUL, ['Yes, please!']).then(d => { + tradeAction(details); + return d; + }); case 2: - return d.player(DialogueEmote.CALM_TALK_1, ['No, thank you.']) + return d + .player(DialogueEmote.CALM_TALK_1, ['No, thank you.']) .then(async d => d.npc(npc, DialogueEmote.ANNOYED, ['Eh, suit yourself.'])) .then(d => { d.close(); return d; }); - } }); }; @@ -35,6 +34,6 @@ export default { pluginId: 'rs:gem_trader', hooks: [ { type: 'npc_interaction', npcs: 'rs:alkharid_gem_trader', options: 'trade', walkTo: true, handler: tradeAction }, - { type: 'npc_interaction', npcs: 'rs:alkharid_gem_trader', options: 'talk-to', walkTo: true, handler: talkToAction } - ] + { type: 'npc_interaction', npcs: 'rs:alkharid_gem_trader', options: 'talk-to', walkTo: true, handler: talkToAction }, + ], }; diff --git a/src/plugins/npcs/al-kharid/karim.plugin.ts b/src/plugins/npcs/al-kharid/karim.plugin.ts index 15ceaa9e2..633b210d5 100644 --- a/src/plugins/npcs/al-kharid/karim.plugin.ts +++ b/src/plugins/npcs/al-kharid/karim.plugin.ts @@ -1,61 +1,65 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { itemIds } from '@engine/world/config/item-ids'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; import { widgets } from '@engine/config/config-handler'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; +import { itemIds } from '@engine/world/config/item-ids'; import { logger } from '@runejs/common'; -const talkToAction : npcInteractionActionHandler = (details) => { +const talkToAction: npcInteractionActionHandler = details => { const { player, npc } = details; - dialogue([player, { npc, key: 'karim' }], [ - karim => [ Emote.HAPPY, `Would you like to buy a nice kebab? Only one gold.`], - options => [ - `I think i'll give it a miss.`, [ - player => [Emote.DROWZY, `I think i'll give it a miss.`], - ], - `Yes please.`, [ - player => [Emote.HAPPY, `Yes please.`], - execute(() => { - const inventory = player.inventory; - if (inventory.has(itemIds.coins)) { - const index = inventory.findIndex(itemIds.coins); - const item = inventory.items[index]; - - if (!inventory.hasSpace()) { - player.sendMessage(`You don't have enough space in your inventory.`); - return; - } + dialogue( + [player, { npc, key: 'karim' }], + [ + karim => [Emote.HAPPY, `Would you like to buy a nice kebab? Only one gold.`], + options => [ + `I think i'll give it a miss.`, + [player => [Emote.DROWZY, `I think i'll give it a miss.`]], + `Yes please.`, + [ + player => [Emote.HAPPY, `Yes please.`], + execute(() => { + const inventory = player.inventory; + if (inventory.has(itemIds.coins)) { + const index = inventory.findIndex(itemIds.coins); + const item = inventory.items[index]; - if (!item) { - logger.warn(`Could not find item with id ${itemIds.coins} in player inventory. [Karim plugin]`); + if (!inventory.hasSpace()) { + player.sendMessage(`You don't have enough space in your inventory.`); + return; + } + + if (!item) { + logger.warn(`Could not find item with id ${itemIds.coins} in player inventory. [Karim plugin]`); + return; + } + + inventory.remove(index); + if (item.amount !== 1) { + inventory.add({ itemId: itemIds.coins, amount: item.amount - 1 }); + } + + inventory.add({ itemId: itemIds.kebab, amount: 1 }); + player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, inventory); return; } - inventory.remove(index); - if (item.amount !== 1) { - inventory.add( { itemId: itemIds.coins, amount: item.amount - 1 }); + if (!inventory.has(itemIds.coins)) { + dialogue( + [player, { npc, key: 'karim' }], + [ + player => [Emote.ANGRY, `Oops, I forgot to bring any money with me.`], + karim => [Emote.GENERIC, `Come back when you have some.`], + ], + ); } - - inventory.add({ itemId: itemIds.kebab, amount: 1 }); - player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, inventory); - return; - } - - if (!inventory.has(itemIds.coins)) { - dialogue([player, { npc, key: 'karim' }], [ - player => [Emote.ANGRY, `Oops, I forgot to bring any money with me.`], - karim => [Emote.GENERIC, `Come back when you have some.`] - ]); - } - }) - ] - ] - ]); + }), + ], + ], + ], + ); }; export default { pluginId: 'rs:karim', - hooks: [ - { type: 'npc_interaction', npcs: 'rs:alkharid_karim', options: 'talk-to', walkTo: true, handler: talkToAction } - ] + hooks: [{ type: 'npc_interaction', npcs: 'rs:alkharid_karim', options: 'talk-to', walkTo: true, handler: talkToAction }], }; diff --git a/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts b/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts index a5012ddec..08d68e576 100644 --- a/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts +++ b/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts @@ -1,17 +1,17 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; import { findShop } from '@engine/config/config-handler'; - -const tradeAction: npcInteractionActionHandler = ({ player }) => - findShop('rs:louies_armored_legs')?.open(player); +const tradeAction: npcInteractionActionHandler = ({ player }) => findShop('rs:louies_armored_legs')?.open(player); export default { pluginId: 'rs:louie_armored_legs', - hooks: [ { - type: 'npc_interaction', - npcs: 'rs:alkharid_louie', - options: 'trade', - walkTo: true, - handler: tradeAction - }] + hooks: [ + { + type: 'npc_interaction', + npcs: 'rs:alkharid_louie', + options: 'trade', + walkTo: true, + handler: tradeAction, + }, + ], }; diff --git a/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts b/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts index 74911202e..d3eb39de8 100644 --- a/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts +++ b/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts @@ -1,17 +1,17 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; import { findShop } from '@engine/config/config-handler'; - -const tradeAction: npcInteractionActionHandler = ({ player }) => - findShop('rs:ranaels_skirt_store')?.open(player); +const tradeAction: npcInteractionActionHandler = ({ player }) => findShop('rs:ranaels_skirt_store')?.open(player); export default { pluginId: 'rs:ranael_super_skirt', - hooks: [{ - type: 'npc_interaction', - npcs: 'rs:alkharid_ranael', - walkTo: true, - options: 'trade', - handler: tradeAction - }] + hooks: [ + { + type: 'npc_interaction', + npcs: 'rs:alkharid_ranael', + walkTo: true, + options: 'trade', + handler: tradeAction, + }, + ], }; diff --git a/src/plugins/npcs/falador/custom-guards.plugin.ts b/src/plugins/npcs/falador/custom-guards.plugin.ts index 637c5b02f..d81b4c2d7 100644 --- a/src/plugins/npcs/falador/custom-guards.plugin.ts +++ b/src/plugins/npcs/falador/custom-guards.plugin.ts @@ -1,13 +1,13 @@ -import { Position } from '@engine/world/position'; +import type { npcInitActionHandler } from '@engine/action/pipe/npc-init.action'; import { findNpc } from '@engine/config/config-handler'; -import type { Npc } from '@engine/world/actor/npc'; import { randomBetween } from '@engine/util/num'; import { activeWorld } from '@engine/world'; -import type { npcInitActionHandler } from '@engine/action/pipe/npc-init.action'; +import type { Npc } from '@engine/world/actor/npc'; +import { Position } from '@engine/world/position'; import { World } from '@engine/world/world'; -const npcs = ['rs:guard:0', 'rs:guard:1'] -const npcObjects = npcs.map((sNpc) => findNpc(sNpc)); +const npcs = ['rs:guard:0', 'rs:guard:1']; +const npcObjects = npcs.map(sNpc => findNpc(sNpc)); interface DialogueNpcTree { a?: string; @@ -34,12 +34,12 @@ const dialogueTrees: DialogueNpcTree[][] = [ }, { a_anim: 837, - a: 'Oh my god.' + a: 'Oh my god.', }, { b: 'Yeah welcome to the club pal.', - b_anim: 2113 - } + b_anim: 2113, + }, ], [ { @@ -122,23 +122,23 @@ const dialogueTrees: DialogueNpcTree[][] = [ b_anim: 856, b: `Shut up!`, }, - ] -] + ], +]; function startIdleDialogueTree(npc: Npc, closeNpc: Npc, dialogueTree: DialogueNpcTree[]) { - if(npc.busy || closeNpc.busy){ + if (npc.busy || closeNpc.busy) { return; } npc.busy = true; closeNpc.busy = true; npc.face(closeNpc); closeNpc.face(npc); - setTimeout(() => doDialogue(npc,closeNpc,0, dialogueTree), 3 * World.TICK_LENGTH) + setTimeout(() => doDialogue(npc, closeNpc, 0, dialogueTree), 3 * World.TICK_LENGTH); } function doDialogue(a: Npc, b: Npc, dialogueIndex: number, dialogueTree: DialogueNpcTree[]) { a.stopAnimation(); b.stopAnimation(); - if(dialogueIndex > dialogueTree.length-1 || !a.exists || !b.exists) { + if (dialogueIndex > dialogueTree.length - 1 || !a.exists || !b.exists) { a.busy = false; b.busy = false; a.clearFaceActor(); @@ -146,55 +146,53 @@ function doDialogue(a: Npc, b: Npc, dialogueIndex: number, dialogueTree: Dialogu return; } const currentDialogue = dialogueTree[dialogueIndex]; - if(currentDialogue.a) { + if (currentDialogue.a) { a.say(currentDialogue.a); } - if(currentDialogue.b) { + if (currentDialogue.b) { b.say(currentDialogue.b); } - if(currentDialogue.a_anim) { + if (currentDialogue.a_anim) { a.playAnimation(currentDialogue.a_anim); } - if(currentDialogue.b_anim) { + if (currentDialogue.b_anim) { b.playAnimation(currentDialogue.b_anim); } - setTimeout(() => doDialogue(a,b,dialogueIndex+1, dialogueTree), 5 * World.TICK_LENGTH) + setTimeout(() => doDialogue(a, b, dialogueIndex + 1, dialogueTree), 5 * World.TICK_LENGTH); } -const npcIdleAction = (npc: Npc) => { - if(Math.random() >= 0.14) { +const npcIdleAction = (npc: Npc) => { + if (Math.random() >= 0.14) { const currentLocation = new Position(npc.position); const closeNpcs = activeWorld.findNearbyNpcs(currentLocation, 4); for (const closeNpc of closeNpcs) { - if(closeNpc === npc) { + if (closeNpc === npc) { continue; } - if(npcObjects.find((oNpc) => oNpc.gameId === closeNpc.id)) { - if(closeNpc.busy) { + if (npcObjects.find(oNpc => oNpc.gameId === closeNpc.id)) { + if (closeNpc.busy) { continue; } - startIdleDialogueTree(npc, closeNpc, dialogueTrees[randomBetween(0, dialogueTrees.length-1)]); + startIdleDialogueTree(npc, closeNpc, dialogueTrees[randomBetween(0, dialogueTrees.length - 1)]); return; } } } -} +}; const guardInitAction: npcInitActionHandler = ({ npc }) => { // this used to use `setInterval` but will need rewriting to be synced with ticks // see https://github.com/runejs/server/issues/417 - // setInterval(() => npcIdleAction(npc), (Math.floor(Math.random() * 20) + 10) * World.TICK_LENGTH); }; - export default { pluginId: 'promises:custom_guards', hooks: [ { type: 'npc_init', npcs: npcs, - handler: guardInitAction - } - ] + handler: guardInitAction, + }, + ], }; diff --git a/src/plugins/npcs/lumbridge/bob.plugin.ts b/src/plugins/npcs/lumbridge/bob.plugin.ts index c45881831..4ba7cfd16 100644 --- a/src/plugins/npcs/lumbridge/bob.plugin.ts +++ b/src/plugins/npcs/lumbridge/bob.plugin.ts @@ -2,18 +2,17 @@ import type { NpcInteractionActionHook } from '@engine/action/pipe/npc-interacti import { findShop } from '@engine/config/config-handler'; import type { ContentPlugin } from '@engine/plugins/content-plugin'; - const bobHook: NpcInteractionActionHook = { type: 'npc_interaction', npcs: 'rs:lumbridge_bob', options: 'trade', walkTo: true, - handler: ({ player }) => findShop('rs:lumbridge_bobs_axes')?.open(player) + handler: ({ player }) => findShop('rs:lumbridge_bobs_axes')?.open(player), }; const bobPlugin: ContentPlugin = { pluginId: 'rs:bob', - hooks: [ bobHook ] -} + hooks: [bobHook], +}; export default bobPlugin; diff --git a/src/plugins/npcs/lumbridge/hans.plugin.ts b/src/plugins/npcs/lumbridge/hans.plugin.ts index ba71626fa..06cc34512 100644 --- a/src/plugins/npcs/lumbridge/hans.plugin.ts +++ b/src/plugins/npcs/lumbridge/hans.plugin.ts @@ -1,41 +1,41 @@ import type { NpcInteractionActionHook } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, execute, goto } from '@engine/world/actor/dialogue'; -import { giveAchievement, Achievements } from '@engine/world/actor/player/achievements'; +import { Emote, dialogue, execute, goto } from '@engine/world/actor/dialogue'; +import { Achievements, giveAchievement } from '@engine/world/actor/player/achievements'; import { animationIds } from '@engine/world/config/animation-ids'; - const handler = async ({ player, npc }) => { let sadEnding = false; - const dialogueParticipants = [ player, { npc, key: 'hans' }]; + const dialogueParticipants = [player, { npc, key: 'hans' }]; const dialogueTree = [ - hans => [ Emote.GENERIC, `Welcome to RuneJS!` ], - (hans, tag_Hans_Question) => [ Emote.HAPPY, `How do you feel about RuneJS so far?\n` + - `Please take a moment to let us know what you think!` ], - options => ([ - `Love it!`, [ - player => [ Emote.HAPPY, `Loving it so far, thanks for asking!` ], - hans => [ Emote.HAPPY, `You're very welcome! Glad to hear it.` ] - ], - `Kind of cool.`, [ - player => [ Emote.GENERIC, `It's kind of cool, I guess. Bit of a weird gimmick.` ], - hans => [ Emote.HAPPY, `Please let us know if you have any suggestions.` ] + hans => [Emote.GENERIC, `Welcome to RuneJS!`], + (hans, tag_Hans_Question) => [ + Emote.HAPPY, + `How do you feel about RuneJS so far?\n` + `Please take a moment to let us know what you think!`, + ], + options => [ + `Love it!`, + [ + player => [Emote.HAPPY, `Loving it so far, thanks for asking!`], + hans => [Emote.HAPPY, `You're very welcome! Glad to hear it.`], ], - `Not my cup of tea, honestly.`, [ - player => [ Emote.SKEPTICAL, `Not really my cup of tea, but keep at it.` ], - hans => [ Emote.GENERIC, `Thanks for the support!` ] + `Kind of cool.`, + [ + player => [Emote.GENERIC, `It's kind of cool, I guess. Bit of a weird gimmick.`], + hans => [Emote.HAPPY, `Please let us know if you have any suggestions.`], ], - `It's literally the worst.`, [ - player => [ Emote.ANGRY, `Literally the worst thing I've ever seen. You disgust me on a personal level.` ], - hans => [ Emote.SAD, `I-is that so?... Well I'm... I'm sorry to hear that.` ], - execute(() => sadEnding = true) + `Not my cup of tea, honestly.`, + [player => [Emote.SKEPTICAL, `Not really my cup of tea, but keep at it.`], hans => [Emote.GENERIC, `Thanks for the support!`]], + `It's literally the worst.`, + [ + player => [Emote.ANGRY, `Literally the worst thing I've ever seen. You disgust me on a personal level.`], + hans => [Emote.SAD, `I-is that so?... Well I'm... I'm sorry to hear that.`], + execute(() => (sadEnding = true)), ], - `What?`, [ - player => [ Emote.DROWZY, `What?...` ], - goto('tag_Hans_Question') - ] - ]) + `What?`, + [player => [Emote.DROWZY, `What?...`], goto('tag_Hans_Question')], + ], ]; const dialogueSuccessful = await dialogue(dialogueParticipants, dialogueTree); @@ -43,8 +43,8 @@ const handler = async ({ player, npc }) => { npc.clearFaceActor(); player.clearFaceActor(); - if(dialogueSuccessful) { - if(sadEnding) { + if (dialogueSuccessful) { + if (sadEnding) { npc.playAnimation(animationIds.cry); npc.say(`Jerk!`); player.sendMessage(`Hans wanders off rather dejectedly.`); @@ -56,7 +56,6 @@ const handler = async ({ player, npc }) => { } }; - export default { pluginId: 'rs:hans', hooks: [ @@ -65,7 +64,7 @@ export default { npcs: 'rs:hans', options: 'talk-to', walkTo: true, - handler - } as NpcInteractionActionHook - ] + handler, + } as NpcInteractionActionHook, + ], }; diff --git a/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts b/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts index 8748b9553..0ca10176b 100644 --- a/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts +++ b/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts @@ -1,81 +1,118 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, goto } from '@engine/world/actor/dialogue'; +import { Emote, dialogue, goto } from '@engine/world/actor/dialogue'; -const millieDialogue: npcInteractionActionHandler = async (details) => - dialogue([ details.player, { npc: details.npc, key: 'millie' }], [ - millie => [ Emote.GENERIC, `Hello Adventurer. Welcome to Mill Lane Mill. Can I help you?` ], - options => [ - `Who are you?`, [ - player => [ Emote.WONDERING, `Who are you?` ], - millie => [ Emote.HAPPY, `I'm Miss Millicent Miller the Miller of Mill Lane Mill. ` + - `Our family have been milling flour for generations.` ], - player => [ Emote.GENERIC, `It's a good business to be in. People will always need flour.` ], - goto('tag_Mill_Flour') +const millieDialogue: npcInteractionActionHandler = async details => + dialogue( + [details.player, { npc: details.npc, key: 'millie' }], + [ + millie => [Emote.GENERIC, `Hello Adventurer. Welcome to Mill Lane Mill. Can I help you?`], + options => [ + `Who are you?`, + [ + player => [Emote.WONDERING, `Who are you?`], + millie => [ + Emote.HAPPY, + `I'm Miss Millicent Miller the Miller of Mill Lane Mill. ` + `Our family have been milling flour for generations.`, + ], + player => [Emote.GENERIC, `It's a good business to be in. People will always need flour.`], + goto('tag_Mill_Flour'), + ], + `What is this place?`, + [ + player => [Emote.WONDERING, `What is this place?`], + millie => [ + Emote.HAPPY, + `This is Mill Lane Mill. Millers of the finest flour in Gielinor, ` + + `and home to the Miller family for many generations.`, + ], + millie => [Emote.GENERIC, `We take grain from the field nearby and mill into flour.`], + goto('tag_Mill_Flour'), + ], + `How do I mill flour?`, + [ + (player, tag_Mill_Flour) => [Emote.WONDERING, `How do I mill flour?`], + millie => [ + Emote.GENERIC, + `Making flour is pretty easy. First of all you need to get some grain. ` + + `You can pick some from wheat fields. There is one just outside the Mill, but there are ` + + `many others scattered across Gielinor.`, + ], + millie => [ + Emote.GENERIC, + `Feel free to pick wheat from our field! There always seems to be plenty ` + `of wheat there.`, + ], + player => [Emote.WONDERING, `Then I bring my wheat here?`], + millie => [ + Emote.GENERIC, + `Yes, or one of the other mills in Gielinor. They all work the same way. ` + + `Just take your grain to the top floor of the mill (up two ladders, there are three floors ` + + `including this one) and then place some`, + ], + millie => [ + Emote.GENERIC, + `grain into the hopper. Then you need to start the grinding process by ` + + `pulling the hopper lever. You can add more grain, but each time you add grain you have to ` + + `pull the hopper lever again.`, + ], + player => [Emote.WONDERING, `So where does the flour go then?`], + millie => [ + Emote.GENERIC, + `The flour appears in this room here, you'll need a pot to put the flour ` + + `into. One pot will hold the flour made by one load of grain`, + ], + millie => [ + Emote.GENERIC, + `And that's it! You now have some pots of finely ground flour of the ` + + `highest quality. Ideal for making tasty cakes or delicous bread. I'm not a cook so you'll ` + + `have to ask a cook to find`, + ], + millie => [Emote.GENERIC, `out how to bake things.`], + player => [Emote.HAPPY, `Great! Thanks for your help.`], + ], + `I'm fine, thanks.`, + [player => [Emote.GENERIC, `I'm fine, thanks.`]], ], - `What is this place?`, [ - player => [ Emote.WONDERING, `What is this place?` ], - millie => [ Emote.HAPPY, `This is Mill Lane Mill. Millers of the finest flour in Gielinor, ` + - `and home to the Miller family for many generations.` ], - millie => [ Emote.GENERIC, `We take grain from the field nearby and mill into flour.` ], - goto('tag_Mill_Flour') - ], - `How do I mill flour?`, [ - (player, tag_Mill_Flour) => [ Emote.WONDERING, `How do I mill flour?` ], - millie => [ Emote.GENERIC, `Making flour is pretty easy. First of all you need to get some grain. ` + - `You can pick some from wheat fields. There is one just outside the Mill, but there are ` + - `many others scattered across Gielinor.` ], - millie => [ Emote.GENERIC, `Feel free to pick wheat from our field! There always seems to be plenty ` + - `of wheat there.` ], - player => [ Emote.WONDERING, `Then I bring my wheat here?` ], - millie => [ Emote.GENERIC, `Yes, or one of the other mills in Gielinor. They all work the same way. ` + - `Just take your grain to the top floor of the mill (up two ladders, there are three floors ` + - `including this one) and then place some` ], - millie => [ Emote.GENERIC, `grain into the hopper. Then you need to start the grinding process by ` + - `pulling the hopper lever. You can add more grain, but each time you add grain you have to ` + - `pull the hopper lever again.` ], - player => [ Emote.WONDERING, `So where does the flour go then?` ], - millie => [ Emote.GENERIC, `The flour appears in this room here, you'll need a pot to put the flour ` + - `into. One pot will hold the flour made by one load of grain` ], - millie => [ Emote.GENERIC, `And that's it! You now have some pots of finely ground flour of the ` + - `highest quality. Ideal for making tasty cakes or delicous bread. I'm not a cook so you'll ` + - `have to ask a cook to find` ], - millie => [ Emote.GENERIC, `out how to bake things.` ], - player => [ Emote.HAPPY, `Great! Thanks for your help.` ] - ], - `I'm fine, thanks.`, [ - player => [ Emote.GENERIC, `I'm fine, thanks.` ] - ] - ] - ]); + ], + ); -const gillieDialogue: npcInteractionActionHandler = async (details) => - dialogue([ details.player, { npc: details.npc, key: 'gillie' }], [ - gillie => [ Emote.HAPPY, `Hello, I'm Gillie the Milkmaid. What can I do for you?` ], - options => [ - `Who are you?`, [ - player => [ Emote.WONDERING, `Who are you?` ], - gillie => [ Emote.GENERIC, `My name is Gillie Groats. My father is a farmer and I milk the cows for him.` ], - player => [ Emote.WONDERING, `Do you have nay buckets of milk spare?` ], - gillie => [ Emote.GENERIC, `I'm afraid not. We need all of our milk to sell to market, ` + - `but you can milk the cow yourself if you need the milk.` ], - player => [ Emote.GENERIC, `Thanks.` ] +const gillieDialogue: npcInteractionActionHandler = async details => + dialogue( + [details.player, { npc: details.npc, key: 'gillie' }], + [ + gillie => [Emote.HAPPY, `Hello, I'm Gillie the Milkmaid. What can I do for you?`], + options => [ + `Who are you?`, + [ + player => [Emote.WONDERING, `Who are you?`], + gillie => [Emote.GENERIC, `My name is Gillie Groats. My father is a farmer and I milk the cows for him.`], + player => [Emote.WONDERING, `Do you have nay buckets of milk spare?`], + gillie => [ + Emote.GENERIC, + `I'm afraid not. We need all of our milk to sell to market, ` + + `but you can milk the cow yourself if you need the milk.`, + ], + player => [Emote.GENERIC, `Thanks.`], + ], + `So how do you milk a cow then?`, + [ + player => [Emote.WONDERING, `So how do you milk a cow then?`], + gillie => [Emote.HAPPY, `It's very easy. First you need an empty bucket to hold the milk.`], + gillie => [Emote.HAPPY, `Then find a dairy cow to milk - you can't milk just any cow.`], + player => [Emote.SKEPTICAL, `How do I find a dairy cow?`], + gillie => [ + Emote.GENERIC, + `They are easy to spot - they are dark brown and white, unlike ` + + `beef cows, which are light brown and white. We also tether them to a post to stop them ` + + `wandering around all over the place.`, + ], + gillie => [Emote.GENERIC, `There are a couple very near, in this field.`], + gillie => [Emote.GENERIC, `Then just milk the cow and your bucket will fill with tasty, untritious milk.`], + ], + `I'm fine, thanks.`, + [player => [Emote.GENERIC, `I'm fine, thanks.`]], ], - `So how do you milk a cow then?`, [ - player => [ Emote.WONDERING, `So how do you milk a cow then?` ], - gillie => [ Emote.HAPPY, `It's very easy. First you need an empty bucket to hold the milk.` ], - gillie => [ Emote.HAPPY, `Then find a dairy cow to milk - you can't milk just any cow.` ], - player => [ Emote.SKEPTICAL, `How do I find a dairy cow?` ], - gillie => [ Emote.GENERIC, `They are easy to spot - they are dark brown and white, unlike ` + - `beef cows, which are light brown and white. We also tether them to a post to stop them ` + - `wandering around all over the place.` ], - gillie => [ Emote.GENERIC, `There are a couple very near, in this field.` ], - gillie => [ Emote.GENERIC, `Then just milk the cow and your bucket will fill with tasty, untritious milk.` ], - ], - `I'm fine, thanks.`, [ - player => [ Emote.GENERIC, `I'm fine, thanks.` ], - ] - ] - ]); + ], + ); export default { pluginId: 'rs:lumbridge_farm_helpers', @@ -85,13 +122,14 @@ export default { npcs: 'rs:gillie_groats', options: 'talk-to', walkTo: true, - handler: gillieDialogue - }, { + handler: gillieDialogue, + }, + { type: 'npc_interaction', npcs: 'rs:millie_miller', options: 'talk-to', walkTo: true, - handler: millieDialogue - } - ] + handler: millieDialogue, + }, + ], }; diff --git a/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts b/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts index 5d668e16e..2e37cdc24 100644 --- a/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts +++ b/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts @@ -3,8 +3,7 @@ import { findShop } from '@engine/config/config-handler'; const action: npcInteractionActionHandler = ({ player }) => { findShop('rs:lumbridge_general_store')?.open(player); - -} +}; export default { pluginId: 'rs:lumbridge_general_store', hooks: [ @@ -13,7 +12,7 @@ export default { npcs: 'rs:lumbridge_shop_keeper', options: 'trade', walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/npcs/port-sarim/betty.plugin.ts b/src/plugins/npcs/port-sarim/betty.plugin.ts index 0510f580c..9bb668b51 100644 --- a/src/plugins/npcs/port-sarim/betty.plugin.ts +++ b/src/plugins/npcs/port-sarim/betty.plugin.ts @@ -1,34 +1,37 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; import { findShop } from '@engine/config/config-handler'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; +const shopAction: npcInteractionActionHandler = details => findShop('rs:bettys_magic_emporium')?.open(details.player); -const shopAction: npcInteractionActionHandler = (details) => - findShop('rs:bettys_magic_emporium')?.open(details.player); - -const dialogueAction: npcInteractionActionHandler = (details) => { +const dialogueAction: npcInteractionActionHandler = details => { const { player, npc } = details; let openShop = false; - dialogue([details.player, { npc: details.npc, key: 'betty' }], [ - betty => [Emote.HAPPY, `Welcome to the magic emporium.`], - options => [ - `Can I see your wares?`, [ - player => [Emote.HAPPY, `Can I see your wares?`], - execute(() => { - openShop = true; - }) + dialogue( + [details.player, { npc: details.npc, key: 'betty' }], + [ + betty => [Emote.HAPPY, `Welcome to the magic emporium.`], + options => [ + `Can I see your wares?`, + [ + player => [Emote.HAPPY, `Can I see your wares?`], + execute(() => { + openShop = true; + }), + ], + `Sorry I'm not into magic.`, + [ + player => [Emote.GENERIC, `Sorry I'm not into magic.`], + betty => [Emote.HAPPY, `Well, if you see anyone who is into magic, please send them my way.`], + ], ], - `Sorry I'm not into magic.`, [ - player => [Emote.GENERIC, `Sorry I'm not into magic.`], - betty => [Emote.HAPPY, `Well, if you see anyone who is into magic, please send them my way.`] - ] - ] - ]); + ], + ); - if(openShop) { + if (openShop) { shopAction(details); } -} +}; export default { pluginId: 'rs:betty_shop', @@ -38,7 +41,7 @@ export default { npcs: 'rs:betty', options: 'trade', walkTo: true, - handler: shopAction + handler: shopAction, }, { type: 'npc_interaction', @@ -46,7 +49,6 @@ export default { options: 'talk-to', walkTo: true, handler: dialogueAction, - }, - ] + ], }; diff --git a/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts b/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts index 479fc2e6b..f0ccbae46 100644 --- a/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts +++ b/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts @@ -1,158 +1,191 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; -import { itemIds } from '@engine/world/config/item-ids'; import { widgets } from '@engine/config/config-handler'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; +import { itemIds } from '@engine/world/config/item-ids'; - -const talkToBartender : npcInteractionActionHandler = (details) => { +const talkToBartender: npcInteractionActionHandler = details => { const { player, npc } = details; - dialogue([player, { npc, key: 'bartender' }], [ - bartender => [Emote.HAPPY, 'What can I do yer for?'], - options => [ - `A glass of your finest ale please.`, [ - player => [Emote.HAPPY, `A glass of your finest ale please.`], - bartender => [Emote.HAPPY, `No problemo. That'll be 2 coins.`], - execute(() => { - const index = player.inventory.findIndex(itemIds.coins); - const hasCoins = player.inventory.has(itemIds.coins); - - if (!hasCoins) { - dialogue([player, { npc, key: 'bartender' }], [ - player => [Emote.VERY_SAD, `Oh dear. I don't seem to have enough money.`], - ]); - } - - if (hasCoins && (player.inventory.amountInStack(index) >= 2)) { - - const amount = player.inventory.amountInStack(index); - // Check inventory. - if (!player.inventory.hasSpace()) { - player.sendMessage(`You don't have enough space in your inventory.`); - return; + dialogue( + [player, { npc, key: 'bartender' }], + [ + bartender => [Emote.HAPPY, 'What can I do yer for?'], + options => [ + `A glass of your finest ale please.`, + [ + player => [Emote.HAPPY, `A glass of your finest ale please.`], + bartender => [Emote.HAPPY, `No problemo. That'll be 2 coins.`], + execute(() => { + const index = player.inventory.findIndex(itemIds.coins); + const hasCoins = player.inventory.has(itemIds.coins); + + if (!hasCoins) { + dialogue( + [player, { npc, key: 'bartender' }], + [player => [Emote.VERY_SAD, `Oh dear. I don't seem to have enough money.`]], + ); } - // Take the coins - player.inventory.remove(index); - if ((amount - 2) !== 0) { - player.inventory.add({ - itemId: itemIds.coins, - amount: (amount - 2) - }); + if (hasCoins && player.inventory.amountInStack(index) >= 2) { + const amount = player.inventory.amountInStack(index); + // Check inventory. + if (!player.inventory.hasSpace()) { + player.sendMessage(`You don't have enough space in your inventory.`); + return; + } + + // Take the coins + player.inventory.remove(index); + if (amount - 2 !== 0) { + player.inventory.add({ + itemId: itemIds.coins, + amount: amount - 2, + }); + } + + // Give the beer. + player.inventory.add(itemIds.beer); + player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); } - - // Give the beer. - player.inventory.add(itemIds.beer); - player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - } - }), - ], - `Can you recommend where an adventurer might make his fortune?`, [ - player => [Emote.WONDERING, `Can you recommend where an adventurer might make his fortune?`], - bartender => [Emote.LAUGH, `Ooh I don't know if I should be giving away information, makes the game too easy.`], - options => [ - `Oh ah well...`, [ - player => [Emote.WORRIED, `Oh ah well...`] + }), + ], + `Can you recommend where an adventurer might make his fortune?`, + [ + player => [Emote.WONDERING, `Can you recommend where an adventurer might make his fortune?`], + bartender => [Emote.LAUGH, `Ooh I don't know if I should be giving away information, makes the game too easy.`], + options => [ + `Oh ah well...`, + [player => [Emote.WORRIED, `Oh ah well...`]], + `Game? What are you talking about?`, + [ + player => [Emote.WORRIED, `Game? What are you talking about?`], + bartender => [Emote.GENERIC, `This world around us... is an online game... called Old School RuneScape.`], + player => [Emote.GENERIC, `Nope, still don't understand what you are talking about. What does 'online' mean?`], + bartender => [ + Emote.GENERIC, + `It's a sort of connection between magic boxes across the world, big boxes on people's desktops and little ones people can carry. They can talk to each other to play games.`, + ], + player => [Emote.GENERIC, `I give up. You're obviously completely mad!`], + ], + `Just a small clue?`, + [ + player => [Emote.WONDERING, `Just a small clue?`], + bartender => [ + Emote.VERY_SAD, + `Go and talk to the bartender at the Jolly Boar Inn, he doesn't seem to mind giving away clues.`, + ], + ], ], - `Game? What are you talking about?`, [ - player => [Emote.WORRIED, `Game? What are you talking about?`], - bartender => [Emote.GENERIC, `This world around us... is an online game... called Old School RuneScape.`], - player => [Emote.GENERIC, `Nope, still don't understand what you are talking about. What does 'online' mean?`], - bartender => [Emote.GENERIC, `It's a sort of connection between magic boxes across the world, big boxes on people's desktops and little ones people can carry. They can talk to each other to play games.`], - player => [Emote.GENERIC, `I give up. You're obviously completely mad!`] + ], + `Do you know where I can get some good equipment?`, + [ + player => [Emote.WONDERING, `Do you know where I can get some good equipment?`], + bartender => [ + Emote.HAPPY, + `Well, there's the sword shop across the road, or there's also all sorts of shops up around the market.`, ], - `Just a small clue?`, [ - player => [Emote.WONDERING, `Just a small clue?`], - bartender => [Emote.VERY_SAD, `Go and talk to the bartender at the Jolly Boar Inn, he doesn't seem to mind giving away clues.`] - ] - ] + ], ], - `Do you know where I can get some good equipment?`, [ - player => [Emote.WONDERING, `Do you know where I can get some good equipment?`], - bartender => [Emote.HAPPY, `Well, there's the sword shop across the road, or there's also all sorts of shops up around the market.`] - ] - ] - ]); + ], + ); }; -const talkToCook : npcInteractionActionHandler = (details) => { +const talkToCook: npcInteractionActionHandler = details => { const { npc, player } = details; - dialogue([player, { npc, key: 'cook' }], [ - cook => [Emote.ANGRY, `What do you want? I'm busy!`], - options => [ - `Can you sell me any food?`, [ - player => [Emote.WONDERING, `Can you sell me any food?`], - cook => [Emote.GENERIC, `I suppose I could sell you some cabbage, if you're willing to pay for it. Cabbage is good for you.`], - execute(() => { - - const hasCoins = player.inventory.has(itemIds.coins); - const index = player.inventory.findIndex(itemIds.coins); - - // The player doesn't have any coins. - if (!hasCoins) { - dialogue([player, { npc, key: 'cook' }], [ - player => [Emote.VERY_SAD, `Oh, I haven't got any money.`], - cook => [Emote.ANGRY, `Why are you asking me to sell you food if you haven't got any money? Go away!`] - ]); - } - - // The player has enough coins - if (hasCoins && (player.inventory.amountInStack(index) >= 2)) { - const amount = player.inventory.amountInStack(index); - dialogue([player, { npc, key: 'cook' }], [ - options => [ - `Alright I'll buy a cabbage.`, [ - player => [Emote.HAPPY, `Alright I'll buy a cabbage.`], - execute(() => { - - // Check inventory. - if (!player.inventory.hasSpace()) { - player.sendMessage(`You don't have enough space in your inventory.`); - return; - } - - // Take the coins - player.inventory.remove(index); - if ((amount - 2) !== 0) { - player.inventory.add({ - itemId: itemIds.coins, - amount: (amount - 2) - }); - } - - // Give the cabbage. - player.inventory.add(itemIds.cabbage); - player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - }), - cook => [Emote.HAPPY, `It's a deal. Now, make sure you eat it all up. Cabbage is good for you.`], + dialogue( + [player, { npc, key: 'cook' }], + [ + cook => [Emote.ANGRY, `What do you want? I'm busy!`], + options => [ + `Can you sell me any food?`, + [ + player => [Emote.WONDERING, `Can you sell me any food?`], + cook => [ + Emote.GENERIC, + `I suppose I could sell you some cabbage, if you're willing to pay for it. Cabbage is good for you.`, + ], + execute(() => { + const hasCoins = player.inventory.has(itemIds.coins); + const index = player.inventory.findIndex(itemIds.coins); + + // The player doesn't have any coins. + if (!hasCoins) { + dialogue( + [player, { npc, key: 'cook' }], + [ + player => [Emote.VERY_SAD, `Oh, I haven't got any money.`], + cook => [Emote.ANGRY, `Why are you asking me to sell you food if you haven't got any money? Go away!`], ], - `No thanks, I don't like cabbage.`, [ - player => [Emote.GENERIC, `No thanks, I don't like cabbage.`], - cook => [Emote.SAD, `Bah! People these days only appreciate junk food.`] + ); + } + + // The player has enough coins + if (hasCoins && player.inventory.amountInStack(index) >= 2) { + const amount = player.inventory.amountInStack(index); + dialogue( + [player, { npc, key: 'cook' }], + [ + options => [ + `Alright I'll buy a cabbage.`, + [ + player => [Emote.HAPPY, `Alright I'll buy a cabbage.`], + execute(() => { + // Check inventory. + if (!player.inventory.hasSpace()) { + player.sendMessage(`You don't have enough space in your inventory.`); + return; + } + + // Take the coins + player.inventory.remove(index); + if (amount - 2 !== 0) { + player.inventory.add({ + itemId: itemIds.coins, + amount: amount - 2, + }); + } + + // Give the cabbage. + player.inventory.add(itemIds.cabbage); + player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); + }), + cook => [ + Emote.HAPPY, + `It's a deal. Now, make sure you eat it all up. Cabbage is good for you.`, + ], + ], + `No thanks, I don't like cabbage.`, + [ + player => [Emote.GENERIC, `No thanks, I don't like cabbage.`], + cook => [Emote.SAD, `Bah! People these days only appreciate junk food.`], + ], + ], ], - ] - ]); - } - }), - ], - `Can you give any free food?`, [ - // PLAYER: Can you give any free food? - player => [Emote.GENERIC, `Can you give any free food?`], - cook => [Emote.GENERIC, `Can you give my any free money?`], - player => [Emote.GENERIC, `Why should I give you free money?`], - cook => [Emote.GENERIC, `Why should I give you free food?`], - player => [Emote.GENERIC, `Oh, forget it.`], + ); + } + }), + ], + `Can you give any free food?`, + [ + // PLAYER: Can you give any free food? + player => [Emote.GENERIC, `Can you give any free food?`], + cook => [Emote.GENERIC, `Can you give my any free money?`], + player => [Emote.GENERIC, `Why should I give you free money?`], + cook => [Emote.GENERIC, `Why should I give you free food?`], + player => [Emote.GENERIC, `Oh, forget it.`], + ], + `I don't want anything from this horrible kitchen.`, + [ + player => [Emote.SHOCKED, `I don't want anything from this horrible kitchen.`], + cook => [Emote.ANGRY, `How dare you? I put a lot of effort into cleaning this kitchen.`], + cook => [Emote.ANGRY, `My daily sweat and elbow-grease keep this kitchen clean!`], + player => [Emote.GENERIC, `Ewww!`], + cook => [Emote.SAD, `Oh, just leave me alone.`], + ], ], - `I don't want anything from this horrible kitchen.`, [ - player => [Emote.SHOCKED, `I don't want anything from this horrible kitchen.`], - cook => [Emote.ANGRY, `How dare you? I put a lot of effort into cleaning this kitchen.`], - cook => [Emote.ANGRY, `My daily sweat and elbow-grease keep this kitchen clean!`], - player => [Emote.GENERIC, `Ewww!`], - cook => [Emote.SAD, `Oh, just leave me alone.`] - ] - ] - ]); + ], + ); }; export default { @@ -162,10 +195,11 @@ export default { type: 'npc_interaction', npcs: 'rs:blue_moon_innk_bartender', handler: talkToBartender, - }, { + }, + { type: 'npc_interaction', npcs: 'rs:blue_moon_inn_cook', - handler: talkToCook - } - ] + handler: talkToCook, + }, + ], }; diff --git a/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts b/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts index 3d6d573f5..a7e247c9e 100644 --- a/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts +++ b/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts @@ -1,69 +1,80 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, execute, goto } from '@engine/world/actor/dialogue'; -import { itemIds } from '@engine/world/config/item-ids'; import { widgets } from '@engine/config/config-handler'; +import { Emote, dialogue, execute, goto } from '@engine/world/actor/dialogue'; +import { itemIds } from '@engine/world/config/item-ids'; - -const talkTo : npcInteractionActionHandler = (details) => { +const talkTo: npcInteractionActionHandler = details => { const { player, npc } = details; - dialogue([player, { npc, key: 'tutor' }], [ - player => [Emote.GENERIC, `Hello.`], - tutor => [Emote.GENERIC, `Well met! Are you interested in hearing about the art of smithing?`], - options => [ - `How can I train my smithing?`, [ - (player, tag_how_to_train) => [Emote.WONDERING, `How can I train my smithing?`], - tutor => [Emote.GENERIC, `To be able to smith anything, you're going to need one of these beauties.`], - execute(() => { - player.inventory.add(itemIds.hammer); - player.sendMessage('The Master Smithing Tutor gives you a hammer.', true); - player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - }), - tutor => [Emote.GENERIC, `You're going to get your hand on some metal bars.`], - tutor => [Emote.GENERIC, `You could do this by mining your own ores and smelting them at a furnace.`], - tutor => [Emote.GENERIC, `There is a furnace in Lumbridge, just north of the castle opposite the general store.`], - tutor => [Emote.GENERIC, `If you are looking for some ore, there is a mine east of Varrock.`], - tutor => [Emote.GENERIC, `There you can find some copper and tin ore. Don't forget to bring a pickaxe.`], - tutor => [Emote.GENERIC, `When you have your bars, bring them to an anvil to open the smithing interface.`], - tutor => [Emote.GENERIC, `If the item name is in black, this means you do not have the level to smith the item.`], - tutor => [Emote.GENERIC, `If the name is in white, this means you have the level to smith the item.`], - tutor => [Emote.GENERIC, `You will see the bars required to smith the item underneath the name of the item.`], - tutor => [Emote.GENERIC, `If the number of bars is in orange, this means that you do not have enough bars to smith the item.`], - tutor => [Emote.GENERIC, `If it is in green, this means you have enough bars for the item.`], - player => [Emote.GENERIC, `Thanks for the advice.`], - (options) => [ - `What kinds of things can I smith?`, [ - goto('tag_what_kinds') + dialogue( + [player, { npc, key: 'tutor' }], + [ + player => [Emote.GENERIC, `Hello.`], + tutor => [Emote.GENERIC, `Well met! Are you interested in hearing about the art of smithing?`], + options => [ + `How can I train my smithing?`, + [ + (player, tag_how_to_train) => [Emote.WONDERING, `How can I train my smithing?`], + tutor => [Emote.GENERIC, `To be able to smith anything, you're going to need one of these beauties.`], + execute(() => { + player.inventory.add(itemIds.hammer); + player.sendMessage('The Master Smithing Tutor gives you a hammer.', true); + player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); + }), + tutor => [Emote.GENERIC, `You're going to get your hand on some metal bars.`], + tutor => [Emote.GENERIC, `You could do this by mining your own ores and smelting them at a furnace.`], + tutor => [Emote.GENERIC, `There is a furnace in Lumbridge, just north of the castle opposite the general store.`], + tutor => [Emote.GENERIC, `If you are looking for some ore, there is a mine east of Varrock.`], + tutor => [Emote.GENERIC, `There you can find some copper and tin ore. Don't forget to bring a pickaxe.`], + tutor => [Emote.GENERIC, `When you have your bars, bring them to an anvil to open the smithing interface.`], + tutor => [Emote.GENERIC, `If the item name is in black, this means you do not have the level to smith the item.`], + tutor => [Emote.GENERIC, `If the name is in white, this means you have the level to smith the item.`], + tutor => [Emote.GENERIC, `You will see the bars required to smith the item underneath the name of the item.`], + tutor => [ + Emote.GENERIC, + `If the number of bars is in orange, this means that you do not have enough bars to smith the item.`, ], - `Not right now, thank you.`, [ - goto('tag_no_thanks') + tutor => [Emote.GENERIC, `If it is in green, this means you have enough bars for the item.`], + player => [Emote.GENERIC, `Thanks for the advice.`], + options => [ + `What kinds of things can I smith?`, + [goto('tag_what_kinds')], + `Not right now, thank you.`, + [goto('tag_no_thanks')], ], - ] - ], - `What kinds of things can I smith?`, [ - (player, tag_what_kinds) => [Emote.WONDERING, `What kinds of things can I smith?`], - tutor => [Emote.GENERIC, `There are many things you can make, from weapons to your good old fashioned armour.`], - tutor => [Emote.GENERIC, `Weapons are the cheapest things to smith. They range from a measly one bar, all the way to three bars.`], - tutor => [Emote.GENERIC, `Armour can be the costliest item to smith, the cost of each item ranges from a measly one bar all the way up to a whopping five bars.`], - tutor => [Emote.GENERIC, `Some weapons and armours, such as darts, will require you to have gained knowledge on how to smith them.`], - tutor => [Emote.GENERIC, `This is due to the complex nature of the weapon.`], - tutor => [Emote.GENERIC, `You might find other items don't require conventional bars you would gather.`], - tutor => [Emote.GENERIC, `Some may require you to piece back together or even infuse a crystal into a piece of armour.`], - tutor => [Emote.GENERIC, `Is there anything else you want to know?`], - options => [ - `How can i train my smithing?`, [ - goto('tag_how_to_train') + ], + `What kinds of things can I smith?`, + [ + (player, tag_what_kinds) => [Emote.WONDERING, `What kinds of things can I smith?`], + tutor => [Emote.GENERIC, `There are many things you can make, from weapons to your good old fashioned armour.`], + tutor => [ + Emote.GENERIC, + `Weapons are the cheapest things to smith. They range from a measly one bar, all the way to three bars.`, + ], + tutor => [ + Emote.GENERIC, + `Armour can be the costliest item to smith, the cost of each item ranges from a measly one bar all the way up to a whopping five bars.`, + ], + tutor => [ + Emote.GENERIC, + `Some weapons and armours, such as darts, will require you to have gained knowledge on how to smith them.`, + ], + tutor => [Emote.GENERIC, `This is due to the complex nature of the weapon.`], + tutor => [Emote.GENERIC, `You might find other items don't require conventional bars you would gather.`], + tutor => [ + Emote.GENERIC, + `Some may require you to piece back together or even infuse a crystal into a piece of armour.`, ], - `No, thank you.`, [ - goto('tag_no_thanks') - ] - ] + tutor => [Emote.GENERIC, `Is there anything else you want to know?`], + options => [`How can i train my smithing?`, [goto('tag_how_to_train')], `No, thank you.`, [goto('tag_no_thanks')]], + ], + `Not right now, thank you.`, + [ + (player, tag_no_thanks) => [Emote.GENERIC, `Not right now, thank you.`], + tutor => [Emote.GENERIC, `Well, just come back any time you want to know anything!`], + ], ], - `Not right now, thank you.`, [ - (player, tag_no_thanks) => [Emote.GENERIC, `Not right now, thank you.`], - tutor => [Emote.GENERIC, `Well, just come back any time you want to know anything!`] - ] - ] - ]); + ], + ); }; export default { @@ -72,9 +83,9 @@ export default { { type: 'npc_interaction', npcs: 'rs:master_smithing_tutor', - options: [ 'talk-to' ], + options: ['talk-to'], walkTo: true, - handler: talkTo - } - ] + handler: talkTo, + }, + ], }; diff --git a/src/plugins/npcs/varrock/wilough.plugin.ts b/src/plugins/npcs/varrock/wilough.plugin.ts index d7435dac1..92670aa5a 100644 --- a/src/plugins/npcs/varrock/wilough.plugin.ts +++ b/src/plugins/npcs/varrock/wilough.plugin.ts @@ -1,20 +1,22 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote } from '@engine/world/actor/dialogue'; import { findNpc } from '@engine/config/config-handler'; +import { Emote, dialogue } from '@engine/world/actor/dialogue'; - -const talkTo : npcInteractionActionHandler = (details) => { +const talkTo: npcInteractionActionHandler = details => { const { player, npc } = details; const shilop = findNpc('rs:varrock_shilop'); - dialogue([player, { npc, key: 'wilough' }, { npc: shilop.gameId, key: 'shilop' }], [ - player => [Emote.GENERIC, `Hello again.`], - wilough => [Emote.GENERIC, `You think you're tough do you?`], - player => [Emote.GENERIC, `Pardon?`], - wilough => [Emote.ANGRY, `I can beat anyone up!`], - shilop => [Emote.BLANK_STARE, `He can you know!`], - player => [Emote.BLANK_STARE, `Really?`] - ]); + dialogue( + [player, { npc, key: 'wilough' }, { npc: shilop.gameId, key: 'shilop' }], + [ + player => [Emote.GENERIC, `Hello again.`], + wilough => [Emote.GENERIC, `You think you're tough do you?`], + player => [Emote.GENERIC, `Pardon?`], + wilough => [Emote.ANGRY, `I can beat anyone up!`], + shilop => [Emote.BLANK_STARE, `He can you know!`], + player => [Emote.BLANK_STARE, `Really?`], + ], + ); }; export default { @@ -23,9 +25,9 @@ export default { { npcs: 'rs:varrock_wilough', type: 'npc_interaction', - options: [ 'talk-to' ], + options: ['talk-to'], walkTo: true, - handler: talkTo - } - ] + handler: talkTo, + }, + ], }; diff --git a/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts b/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts index d1d4b9f1a..708c44495 100644 --- a/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts +++ b/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts @@ -1,39 +1,44 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; import { findShop } from '@engine/config/config-handler'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; +const tradeAction: npcInteractionActionHandler = ({ player }) => findShop('rs:zaffs_superior_staffs')?.open(player); -const tradeAction: npcInteractionActionHandler = ({ player }) => - findShop('rs:zaffs_superior_staffs')?.open(player); - -const talkToAction : npcInteractionActionHandler = (details) => { +const talkToAction: npcInteractionActionHandler = details => { const { player, npc } = details; - dialogue([player, { npc, key: 'zaff' }], [ - zaff => [ Emote.GENERIC, `Would you like to buy or sell some staffs?`], - options => [ - `Yes, please!`, [ - execute(() => { - tradeAction(details); - }) - ], - - 'Have you any extra stock of battlestaffs I can buy?', [ - player => [Emote.GENERIC, 'Have you any extra stock of battlestaffs I can buy?'], - zaff => [Emote.WONDERING, 'No, I\'m afraid I can\'t help you.'], - execute(() => { - player.sendMessage('You must complete the Varrock Achievement Diary before you can access Zaff\'s extra battlestaff stock.'); - }) + dialogue( + [player, { npc, key: 'zaff' }], + [ + zaff => [Emote.GENERIC, `Would you like to buy or sell some staffs?`], + options => [ + `Yes, please!`, + [ + execute(() => { + tradeAction(details); + }), + ], + + 'Have you any extra stock of battlestaffs I can buy?', + [ + player => [Emote.GENERIC, 'Have you any extra stock of battlestaffs I can buy?'], + zaff => [Emote.WONDERING, "No, I'm afraid I can't help you."], + execute(() => { + player.sendMessage( + "You must complete the Varrock Achievement Diary before you can access Zaff's extra battlestaff stock.", + ); + }), + ], + + 'No, thank you.', + [ + player => [Emote.GENERIC, 'No, thank you.'], + zaff => [Emote.GENERIC, "Well 'stick' your head in if you change your mind."], + player => [Emote.GENERIC, "Huh, terrible pun! You just can't get the 'staff' these days!"], + ], ], - - 'No, thank you.', [ - player => [Emote.GENERIC, 'No, thank you.'], - zaff => [Emote.GENERIC, 'Well \'stick\' your head in if you change your mind.'], - player => [Emote.GENERIC, 'Huh, terrible pun! You just can\'t get the \'staff\' these days!'] - ] - - ] - ]); + ], + ); }; export default { @@ -44,13 +49,14 @@ export default { npcs: 'rs:varrock_zaff', options: 'trade', walkTo: true, - handler: tradeAction - }, { + handler: tradeAction, + }, + { type: 'npc_interaction', npcs: 'rs:varrock_zaff', options: 'talk-to', walkTo: true, - handler: talkToAction - } - ] + handler: talkToAction, + }, + ], }; diff --git a/src/plugins/objects/bank/bank.plugin.ts b/src/plugins/objects/bank/bank.plugin.ts index 20b48f4e7..a55cbcad7 100644 --- a/src/plugins/objects/bank/bank.plugin.ts +++ b/src/plugins/objects/bank/bank.plugin.ts @@ -1,16 +1,15 @@ +import type { buttonActionHandler } from '@engine/action/pipe/button.action'; +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { widgets } from '@engine/config/config-handler'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; +import type { Player } from '@engine/world/actor/player/player'; import { objectIds } from '@engine/world/config/object-ids'; import { widgetScripts } from '@engine/world/config/widget'; -import type { ItemContainer } from '@engine/world/items/item-container'; import type { Item } from '@engine/world/items/item'; import { fromNote, toNote } from '@engine/world/items/item'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; -import { widgets } from '@engine/config/config-handler'; -import type { Player } from '@engine/world/actor/player/player'; +import type { ItemContainer } from '@engine/world/items/item-container'; import { logger } from '@runejs/common'; -import type { buttonActionHandler } from '@engine/action/pipe/button.action'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; -import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; - const buttonIds: number[] = [ 92, // as note @@ -22,11 +21,11 @@ const buttonIds: number[] = [ export const openBankInterface: objectInteractionActionHandler = ({ player }) => { player.interfaceState.openWidget(widgets.bank.screenWidget.widgetId, { slot: 'screen', - multi: true + multi: true, }); player.interfaceState.openWidget(widgets.bank.tabWidget.widgetId, { slot: 'tabarea', - multi: true + multi: true, }); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.tabWidget, player.inventory); @@ -37,11 +36,11 @@ export const openBankInterface: objectInteractionActionHandler = ({ player }) => export const openPinSettings: objectInteractionActionHandler = ({ player }) => { player.interfaceState.openWidget(widgets.bank.pinSettingsWidget.widgetId, { - slot: 'screen' + slot: 'screen', }); }; -export const depositItem: itemInteractionActionHandler = (details) => { +export const depositItem: itemInteractionActionHandler = details => { // Check if player might be spawning widget client-side if (!details.player.interfaceState.findWidget(widgets.bank.screenWidget.widgetId)) { return; @@ -86,7 +85,7 @@ export const depositItem: itemInteractionActionHandler = (details) => { const slotsWithItem = playerInventory.findAll(details.itemId); let itemAmount = 0; - slotsWithItem.forEach((slot) => { + slotsWithItem.forEach(slot => { const item = playerInventory.items[slot]; if (!item) { @@ -110,15 +109,14 @@ export const depositItem: itemInteractionActionHandler = (details) => { const itemToAdd: Item = { itemId: itemIdToAdd, - amount: removeFromContainer(playerInventory, details.itemId, countToRemove) + amount: removeFromContainer(playerInventory, details.itemId, countToRemove), }; playerBank.addStacking(itemToAdd); updateBankingInterface(details.player); }; - -export const withdrawItem: itemInteractionActionHandler = (details) => { +export const withdrawItem: itemInteractionActionHandler = details => { // Check if player might be spawning widget client-side if (!details.player.interfaceState.findWidget(widgets.bank.screenWidget.widgetId)) { return; @@ -191,13 +189,13 @@ export const withdrawItem: itemInteractionActionHandler = (details) => { const itemToAdd: Item = { itemId: itemIdToAdd, - amount: removeFromContainer(playerBank, details.itemId, countToRemove) + amount: removeFromContainer(playerBank, details.itemId, countToRemove), }; if (stackable) { playerInventory.add({ itemId: itemToAdd.itemId, amount: itemToAdd.amount }); } else { - for(let count = 0; count < itemToAdd.amount; count++) { + for (let count = 0; count < itemToAdd.amount; count++) { playerInventory.add({ itemId: itemToAdd.itemId, amount: 1 }); } } @@ -209,7 +207,7 @@ export const updateBankingInterface = (player: Player) => { player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.tabWidget, player.inventory); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.screenWidget, player.bank); -} +}; /** * Removes an item from a container (e.g. bank or inventory) and returns the amount of items it removed. @@ -242,9 +240,9 @@ export const removeFromContainer = (from: ItemContainer, itemId: number, amount: } return resultingAmount; -} +}; -export const btnAction: buttonActionHandler = (details) => { +export const btnAction: buttonActionHandler = details => { const { player, buttonId } = details; player.settingChanged(buttonId); @@ -262,33 +260,39 @@ export const btnAction: buttonActionHandler = (details) => { player.settings[config.setting] = config.value; }; -const useBankBoothAction : objectInteractionActionHandler = async (details) => { +const useBankBoothAction: objectInteractionActionHandler = async details => { const { player } = details; let openBank = false; let openPin = false; - await dialogue([player, { npc: 'rs:generic_banker', key: 'banker' }], [ - banker => [Emote.HAPPY, `Good day, how can I help you?`], - options => [ - `I'd Like to access my bank account, please.`, [ - execute(() => { - openBank = true; - }) - ], - `I'd like to check my PIN settings.`, [ - execute(() => { - openPin = true; - }) + await dialogue( + [player, { npc: 'rs:generic_banker', key: 'banker' }], + [ + banker => [Emote.HAPPY, `Good day, how can I help you?`], + options => [ + `I'd Like to access my bank account, please.`, + [ + execute(() => { + openBank = true; + }), + ], + `I'd like to check my PIN settings.`, + [ + execute(() => { + openPin = true; + }), + ], + `What is this place?`, + [ + player => [Emote.WONDERING, `What is this place?`], + banker => [Emote.HAPPY, `This is a branch of the Bank of Gielinor. We have branches in many towns.`], + player => [Emote.WONDERING, `And what do you do?`], + banker => [Emote.GENERIC, `We will look after your items and money for you.`], + banker => [Emote.GENERIC, `Leave your valuables with us if you want to keep them safe.`], + ], ], - `What is this place?`, [ - player => [Emote.WONDERING, `What is this place?`], - banker => [Emote.HAPPY, `This is a branch of the Bank of Gielinor. We have branches in many towns.`], - player => [Emote.WONDERING, `And what do you do?`], - banker => [Emote.GENERIC, `We will look after your items and money for you.`], - banker => [Emote.GENERIC, `Leave your valuables with us if you want to keep them safe.`] - ] - ] - ]); + ], + ); if (openBank) { openBankInterface(details as any); @@ -303,30 +307,34 @@ export default { { type: 'object_interaction', objectIds: objectIds.bankBooth, - options: [ 'use' ], + options: ['use'], walkTo: true, - handler: useBankBoothAction - }, { + handler: useBankBoothAction, + }, + { type: 'object_interaction', objectIds: objectIds.bankBooth, - options: [ 'use-quickly' ], + options: ['use-quickly'], walkTo: true, - handler: openBankInterface - }, { + handler: openBankInterface, + }, + { type: 'item_interaction', widgets: widgets.bank.tabWidget, - options: [ 'deposit-1', 'deposit-5', 'deposit-10', 'deposit-all' ], + options: ['deposit-1', 'deposit-5', 'deposit-10', 'deposit-all'], handler: depositItem, - }, { + }, + { type: 'item_interaction', widgets: widgets.bank.screenWidget, - options: [ 'withdraw-1', 'withdraw-5', 'withdraw-10', 'withdraw-all' ], + options: ['withdraw-1', 'withdraw-5', 'withdraw-10', 'withdraw-all'], handler: withdrawItem, - }, { + }, + { type: 'button', widgetId: widgets.bank.screenWidget.widgetId, buttonIds: buttonIds, - handler: btnAction - } - ] + handler: btnAction, + }, + ], }; diff --git a/src/plugins/objects/bank/deposit-box.plugin.ts b/src/plugins/objects/bank/deposit-box.plugin.ts index 249184130..49b96f714 100644 --- a/src/plugins/objects/bank/deposit-box.plugin.ts +++ b/src/plugins/objects/bank/deposit-box.plugin.ts @@ -1,28 +1,24 @@ +import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { widgets } from '@engine/config/config-handler'; import { objectIds } from '@engine/world/config/object-ids'; import type { Item } from '@engine/world/items/item'; import { fromNote } from '@engine/world/items/item'; -import { widgets } from '@engine/config/config-handler'; -import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; -import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; export const openDepositBoxInterface: objectInteractionActionHandler = ({ player }) => { - player.interfaceState.openWidget(widgets.bank.depositBoxWidget.widgetId, { slot: 'screen', - multi: true + multi: true, }); player.interfaceState.openWidget(widgets.disabledTab, { slot: 'tabarea', - multi: true + multi: true, }); - player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.depositBoxWidget, player.inventory); }; - - -export const depositItem: itemInteractionActionHandler = (details) => { +export const depositItem: itemInteractionActionHandler = details => { // Check if player might be spawning widget clientside if (!details.player.interfaceState.findWidget(widgets.bank.depositBoxWidget.widgetId)) { return; @@ -47,13 +43,12 @@ export const depositItem: itemInteractionActionHandler = (details) => { countToRemove = +details.option.replace('deposit-', ''); } - const playerInventory = details.player.inventory; const playerBank = details.player.bank; const slotsWithItem = playerInventory.findAll(details.itemId); let itemAmount: number = 0; - slotsWithItem.forEach((slot) => { + slotsWithItem.forEach(slot => { const item = playerInventory.items[slot]; if (!item) { @@ -75,7 +70,6 @@ export const depositItem: itemInteractionActionHandler = (details) => { return; } - const itemToAdd: Item = { itemId: itemIdToAdd, amount: 0 }; while (countToRemove > 0 && playerInventory.has(details.itemId)) { const invIndex = playerInventory.findIndex(details.itemId); @@ -98,27 +92,25 @@ export const depositItem: itemInteractionActionHandler = (details) => { playerBank.addStacking(itemToAdd); - details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.depositBoxWidget, details.player.inventory); }; - - export default { pluginId: 'rs:bank_deposit_box', hooks: [ { type: 'object_interaction', objectIds: objectIds.depositBox, - options: [ 'deposit' ], + options: ['deposit'], walkTo: true, - handler: openDepositBoxInterface - }, { + handler: openDepositBoxInterface, + }, + { type: 'item_interaction', widgets: widgets.bank.depositBoxWidget, - options: [ 'deposit-1', 'deposit-5', 'deposit-10', 'deposit-all' ], + options: ['deposit-1', 'deposit-5', 'deposit-10', 'deposit-all'], handler: depositItem, - } - ] + }, + ], }; diff --git a/src/plugins/objects/cows/cow.plugin.ts b/src/plugins/objects/cows/cow.plugin.ts index b1c5eaf0a..e189bf323 100644 --- a/src/plugins/objects/cows/cow.plugin.ts +++ b/src/plugins/objects/cows/cow.plugin.ts @@ -1,23 +1,20 @@ -import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; +import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; +import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem, findNpc } from '@engine/config/config-handler'; +import { DialogueEmote, dialogueAction } from '@engine/world/actor/player/dialogue-action'; +import type { Player } from '@engine/world/actor/player/player'; import { animationIds } from '@engine/world/config/animation-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; import { itemIds } from '@engine/world/config/item-ids'; import { objectIds } from '@engine/world/config/object-ids'; -import type { Player } from '@engine/world/actor/player/player'; -import { findItem, findNpc } from '@engine/config/config-handler'; +import { soundIds } from '@engine/world/config/sound-ids'; import type { ObjectConfig } from '@runejs/filestore'; -import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; -import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; - -function milkCow(details: { objectConfig: ObjectConfig, player: Player }): void { +function milkCow(details: { objectConfig: ObjectConfig; player: Player }): void { const { player, objectConfig } = details; const emptyBucketItem = findItem(itemIds.bucket); // TODO: `findItem` should probably throw this error internally. if (emptyBucketItem === null) { - throw new Error( - 'Failed to milk cow as no item matching bucket was found.', - ); + throw new Error('Failed to milk cow as no item matching bucket was found.'); } if (player.hasItemInInventory(itemIds.bucket)) { @@ -33,9 +30,19 @@ function milkCow(details: { objectConfig: ObjectConfig, player: Player }): void dialogueAction(player) .then(async d => d.npc(gillieId, DialogueEmote.LAUGH_1, [`Tee hee! You've never milked a cow before, have you?`])) .then(async d => d.player(DialogueEmote.CALM_TALK_1, ['Erm... No. How could you tell?'])) - .then(async d => d.npc(gillieId, DialogueEmote.LAUGH_2, [`Because you're spilling milk all over the floor. What a`, 'waste! You need something to hold the milk.'])) + .then(async d => + d.npc(gillieId, DialogueEmote.LAUGH_2, [ + `Because you're spilling milk all over the floor. What a`, + 'waste! You need something to hold the milk.', + ]), + ) .then(async d => d.player(DialogueEmote.CONSIDERING, [`Ah yes, I really should have guessed that one, shouldn't`, 'I?'])) - .then(async d => d.npc(gillieId, DialogueEmote.LAUGH_2, [`You're from the city aren't you... Try it again with a`, `${emptyBucketItem.name.toLowerCase()}.`])) + .then(async d => + d.npc(gillieId, DialogueEmote.LAUGH_2, [ + `You're from the city aren't you... Try it again with a`, + `${emptyBucketItem.name.toLowerCase()}.`, + ]), + ) .then(async d => d.player(DialogueEmote.CALM_TALK_2, [`Right, I'll do that.`])) .then(d => { d.close(); @@ -43,9 +50,9 @@ function milkCow(details: { objectConfig: ObjectConfig, player: Player }): void } } -export const actionItem: itemOnObjectActionHandler = (details) => milkCow(details); +export const actionItem: itemOnObjectActionHandler = details => milkCow(details); -export const actionInteract: objectInteractionActionHandler = (details) => milkCow(details); +export const actionInteract: objectInteractionActionHandler = details => milkCow(details); export default { pluginId: 'rs:cow_milking', @@ -55,14 +62,14 @@ export default { objectIds: objectIds.milkableCow, options: 'milk', walkTo: true, - handler: actionInteract + handler: actionInteract, }, { type: 'item_on_object', objectIds: objectIds.milkableCow, itemIds: itemIds.bucket, walkTo: true, - handler: actionItem - } - ] + handler: actionItem, + }, + ], }; diff --git a/src/plugins/objects/crates/crates.plugin.ts b/src/plugins/objects/crates/crates.plugin.ts index 27e5358f0..9d794c049 100644 --- a/src/plugins/objects/crates/crates.plugin.ts +++ b/src/plugins/objects/crates/crates.plugin.ts @@ -1,8 +1,8 @@ -import { findItem, widgets } from '@engine/config/config-handler'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem, widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; -export const action: objectInteractionActionHandler = (details) => { +export const action: objectInteractionActionHandler = details => { const veggies = [itemIds.onion, itemIds.grain, itemIds.cabbage]; details.player.busy = true; details.player.playAnimation(827); @@ -29,10 +29,10 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ 366, 357, 355 ], - options: ['loot', 'search', 'examine' ], + objectIds: [366, 357, 355], + options: ['loot', 'search', 'examine'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/doors/door.plugin.ts b/src/plugins/objects/doors/door.plugin.ts index 3a784811c..323a6e760 100644 --- a/src/plugins/objects/doors/door.plugin.ts +++ b/src/plugins/objects/doors/door.plugin.ts @@ -1,6 +1,6 @@ -import { directionData, WNES } from '@engine/world/direction'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; import { soundIds } from '@engine/world/config/sound-ids'; +import { WNES, directionData } from '@engine/world/direction'; import type { LandscapeObject } from '@runejs/filestore'; // @TODO move to yaml config @@ -8,56 +8,56 @@ const doors = [ { closed: 1530, open: 1531, - hinge: 'RIGHT' + hinge: 'RIGHT', }, { closed: 11707, open: 11708, - hinge: 'RIGHT' + hinge: 'RIGHT', }, { closed: 1533, open: 1534, - hinge: 'RIGHT' + hinge: 'RIGHT', }, { closed: 1516, open: 1517, - hinge: 'LEFT' + hinge: 'LEFT', }, { closed: 1519, open: 1520, - hinge: 'RIGHT' + hinge: 'RIGHT', }, { closed: 1536, open: 1537, - hinge: 'LEFT' + hinge: 'LEFT', }, { closed: 11993, open: 11994, - hinge: 'RIGHT' + hinge: 'RIGHT', }, { closed: 13001, open: 13002, - hinge: 'RIGHT' - } + hinge: 'RIGHT', + }, ]; const leftHingeDir: { [key: string]: string } = { - 'NORTH': 'WEST', - 'SOUTH': 'EAST', - 'WEST': 'SOUTH', - 'EAST': 'NORTH' + NORTH: 'WEST', + SOUTH: 'EAST', + WEST: 'SOUTH', + EAST: 'NORTH', }; const rightHingeDir: { [key: string]: string } = { - 'NORTH': 'EAST', - 'SOUTH': 'WEST', - 'WEST': 'NORTH', - 'EAST': 'SOUTH' + NORTH: 'EAST', + SOUTH: 'WEST', + WEST: 'NORTH', + EAST: 'SOUTH', }; export const action: objectInteractionActionHandler = ({ player, object: door, position, cacheOriginal }): void => { @@ -65,9 +65,9 @@ export const action: objectInteractionActionHandler = ({ player, object: door, p let doorConfig = doors.find(d => d.closed === door.objectId); let hingeConfig; let replacementDoorId: number; - if(!doorConfig) { + if (!doorConfig) { doorConfig = doors.find(d => d.open === door.objectId); - if(!doorConfig) { + if (!doorConfig) { return; } @@ -89,7 +89,7 @@ export const action: objectInteractionActionHandler = ({ player, object: door, p y: endPosition.y, level: position.level, type: door.type, - orientation: directionData[endDir].rotation + orientation: directionData[endDir].rotation, }; player.instance.toggleGameObjects(replacementDoor, door, !cacheOriginal); @@ -102,11 +102,10 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ 1530, 4465, 4467, 3014, 3017, 3018, - 3019, 1536, 1537, 1533, 1531, 1534, 12348, 11993, 11994, 13001, 13002 ], - options: [ 'open', 'close' ], + objectIds: [1530, 4465, 4467, 3014, 3017, 3018, 3019, 1536, 1537, 1533, 1531, 1534, 12348, 11993, 11994, 13001, 13002], + options: ['open', 'close'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/doors/double-door.plugin.ts b/src/plugins/objects/doors/double-door.plugin.ts index 4cd288d89..e3aeed9b8 100644 --- a/src/plugins/objects/doors/double-door.plugin.ts +++ b/src/plugins/objects/doors/double-door.plugin.ts @@ -1,47 +1,47 @@ -import { Position } from '@engine/world/position'; -import { WNES } from '@engine/world/direction'; -import { logger } from '@runejs/common'; -import { action as doorAction } from '@plugins/objects/doors/door.plugin'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; import { activeWorld } from '@engine/world'; +import { WNES } from '@engine/world/direction'; +import { Position } from '@engine/world/position'; +import { action as doorAction } from '@plugins/objects/doors/door.plugin'; +import { logger } from '@runejs/common'; const doubleDoors = [ { - closed: [ 1516, 1519 ], - open: [ 1517, 1520 ] - } + closed: [1516, 1519], + open: [1517, 1520], + }, ]; const closingDelta = { - 'WEST': { x: 1, y: 0 }, - 'EAST': { x: -1, y: 0 }, - 'NORTH': { x: 0, y: -1 }, - 'SOUTH': { x: 0, y: 1 } + WEST: { x: 1, y: 0 }, + EAST: { x: -1, y: 0 }, + NORTH: { x: 0, y: -1 }, + SOUTH: { x: 0, y: 1 }, }; const openingDelta = { - 'LEFT': { - 'WEST': { x: 0, y: 1 }, - 'EAST': { x: 0, y: -1 }, - 'NORTH': { x: 1, y: 0 }, - 'SOUTH': { x: -1, y: 0 } + LEFT: { + WEST: { x: 0, y: 1 }, + EAST: { x: 0, y: -1 }, + NORTH: { x: 1, y: 0 }, + SOUTH: { x: -1, y: 0 }, + }, + RIGHT: { + WEST: { x: 0, y: -1 }, + EAST: { x: 0, y: 1 }, + NORTH: { x: -1, y: 0 }, + SOUTH: { x: 1, y: 0 }, }, - 'RIGHT': { - 'WEST': { x: 0, y: -1 }, - 'EAST': { x: 0, y: 1 }, - 'NORTH': { x: -1, y: 0 }, - 'SOUTH': { x: 1, y: 0 } - } }; -const action: objectInteractionActionHandler = (details) => { +const action: objectInteractionActionHandler = details => { const { player, object: door, position, cacheOriginal } = details; let doorConfig = doubleDoors.find(d => d.closed.indexOf(door.objectId) !== -1); let doorIds: number[]; let opening = true; - if(!doorConfig) { + if (!doorConfig) { doorConfig = doubleDoors.find(d => d.open.indexOf(door.objectId) !== -1); - if(!doorConfig) { + if (!doorConfig) { return; } @@ -59,7 +59,7 @@ const action: objectInteractionActionHandler = (details) => { let deltaY = 0; const otherDoorId = hinge === 'LEFT' ? rightDoorId : leftDoorId; - if(!opening) { + if (!opening) { deltaX += closingDelta[direction].x; deltaY += closingDelta[direction].y; } else { @@ -67,7 +67,7 @@ const action: objectInteractionActionHandler = (details) => { deltaY += openingDelta[hinge][direction].y; } - if(!otherDoorId || (deltaX === 0 && deltaY === 0)) { + if (!otherDoorId || (deltaX === 0 && deltaY === 0)) { logger.error('Improperly handled double door at ' + door.x + ',' + door.y + ',' + door.level); return; } @@ -75,7 +75,7 @@ const action: objectInteractionActionHandler = (details) => { const otherDoorPosition = new Position(door.x + deltaX, door.y + deltaY, door.level); const { object: otherDoor } = activeWorld.findObjectAtLocation(player, otherDoorId, otherDoorPosition); - if(!otherDoor) { + if (!otherDoor) { return; } @@ -84,8 +84,9 @@ const action: objectInteractionActionHandler = (details) => { player, object: door, objectConfig: null as any, - position, cacheOriginal, - option: opening ? 'open' : 'close' + position, + cacheOriginal, + option: opening ? 'open' : 'close', }); doorAction({ player, @@ -93,7 +94,7 @@ const action: objectInteractionActionHandler = (details) => { objectConfig: null as any, position: otherDoorPosition, cacheOriginal, - option: opening ? 'open' : 'close' + option: opening ? 'open' : 'close', }); }; @@ -101,8 +102,11 @@ export default { pluginId: 'rs:double_doors', hooks: [ { - type: 'object_interaction', objectIds: [ 1519, 1516, 1517, 1520 ], - options: [ 'open', 'close' ], walkTo: true, handler: action - } - ] + type: 'object_interaction', + objectIds: [1519, 1516, 1517, 1520], + options: ['open', 'close'], + walkTo: true, + handler: action, + }, + ], }; diff --git a/src/plugins/objects/doors/gate.plugin.ts b/src/plugins/objects/doors/gate.plugin.ts index cc813ffc8..20788acf2 100644 --- a/src/plugins/objects/doors/gate.plugin.ts +++ b/src/plugins/objects/doors/gate.plugin.ts @@ -1,11 +1,11 @@ -import { Position } from '@engine/world/position'; -import { directionData, WNES } from '@engine/world/direction'; -import { logger } from '@runejs/common'; -import type { ModifiedLandscapeObject } from '@engine/world/map/landscape-object'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { activeWorld } from '@engine/world'; import { soundIds } from '@engine/world/config/sound-ids'; +import { WNES, directionData } from '@engine/world/direction'; import type { Chunk } from '@engine/world/map/chunk'; -import { activeWorld } from '@engine/world'; +import type { ModifiedLandscapeObject } from '@engine/world/map/landscape-object'; +import { Position } from '@engine/world/position'; +import { logger } from '@runejs/common'; const gates = [ { @@ -13,23 +13,23 @@ const gates = [ mainOpen: 1552, hinge: 'LEFT', secondary: 1553, - secondaryOpen: 1556 + secondaryOpen: 1556, }, { main: 12986, mainOpen: 12988, hinge: 'LEFT', secondary: 12987, - secondaryOpen: 12989 - } + secondaryOpen: 12989, + }, ]; // @TODO clean up this disgusting code -const action: objectInteractionActionHandler = (details) => { +const action: objectInteractionActionHandler = details => { const { player, cacheOriginal } = details; let { object: gate, position } = details; - if((gate as ModifiedLandscapeObject).metadata) { + if ((gate as ModifiedLandscapeObject).metadata) { const metadata = (gate as ModifiedLandscapeObject).metadata; if (!metadata) { @@ -50,16 +50,15 @@ const action: objectInteractionActionHandler = (details) => { let hingeChunk: Chunk; let gateSecondPosition: Position | null = null; - if(!details) { + if (!details) { details = gates.find(g => g.secondary === gate.objectId); - if(!details) { + if (!details) { logger.error(`Could not find gate details for gate with id ${gate.objectId} on second pass.`); player.sendMessage('Oops, something went wrong. Please report this to a developer.'); return; } - secondGate = gate; gateSecondPosition = position; clickedSecondary = true; @@ -68,8 +67,8 @@ const action: objectInteractionActionHandler = (details) => { let deltaX = 0; let deltaY = 0; - if(hinge === 'LEFT') { - switch(direction) { + if (hinge === 'LEFT') { + switch (direction) { case 'WEST': deltaY--; break; @@ -83,8 +82,8 @@ const action: objectInteractionActionHandler = (details) => { deltaX++; break; } - } else if(hinge === 'RIGHT') { - switch(direction) { + } else if (hinge === 'RIGHT') { + switch (direction) { case 'WEST': deltaY++; break; @@ -113,7 +112,6 @@ const action: objectInteractionActionHandler = (details) => { logger.error('Could not find main gate for secondary gate at ' + gate.x + ',' + gate.y + ',' + gate.level); player.sendMessage('Oops, something went wrong. Please report this to a developer.'); } - } else { hinge = details.hinge; } @@ -123,8 +121,8 @@ const action: objectInteractionActionHandler = (details) => { let newX = 0; let newY = 0; - if(hinge === 'LEFT') { - switch(direction) { + if (hinge === 'LEFT') { + switch (direction) { case 'WEST': deltaY++; newX--; @@ -142,8 +140,8 @@ const action: objectInteractionActionHandler = (details) => { newY--; break; } - } else if(hinge === 'RIGHT') { - switch(direction) { + } else if (hinge === 'RIGHT') { + switch (direction) { case 'WEST': deltaY--; newX++; @@ -164,26 +162,26 @@ const action: objectInteractionActionHandler = (details) => { } const leftHingeDirections: { [key: string]: string } = { - 'NORTH': 'WEST', - 'SOUTH': 'EAST', - 'WEST': 'SOUTH', - 'EAST': 'NORTH' + NORTH: 'WEST', + SOUTH: 'EAST', + WEST: 'SOUTH', + EAST: 'NORTH', }; const rightHingeDirections: { [key: string]: string } = { - 'NORTH': 'EAST', - 'SOUTH': 'WEST', - 'WEST': 'NORTH', - 'EAST': 'SOUTH' + NORTH: 'EAST', + SOUTH: 'WEST', + WEST: 'NORTH', + EAST: 'SOUTH', }; - if(deltaX === 0 && deltaY === 0) { + if (deltaX === 0 && deltaY === 0) { logger.error('Improperly handled gate at ' + gate.x + ',' + gate.y + ',' + gate.level); return; } const newDirection = hinge === 'LEFT' ? leftHingeDirections[direction] : rightHingeDirections[direction]; - if(!clickedSecondary) { + if (!clickedSecondary) { gateSecondPosition = new Position(gate.x + deltaX, gate.y + deltaY, gate.level); } @@ -195,7 +193,7 @@ const action: objectInteractionActionHandler = (details) => { const gateSecondChunk = activeWorld.chunkManager.getChunkForWorldPosition(gateSecondPosition); - if(!clickedSecondary) { + if (!clickedSecondary) { secondGate = gateSecondChunk.getFilestoreLandscapeObject(details.secondary, gateSecondPosition); } @@ -208,7 +206,7 @@ const action: objectInteractionActionHandler = (details) => { y: newPosition.y, level: newPosition.level, type: gate.type, - orientation: directionData[newDirection].rotation + orientation: directionData[newDirection].rotation, } as ModifiedLandscapeObject; const newSecond = { objectId: details.secondaryOpen, @@ -216,14 +214,14 @@ const action: objectInteractionActionHandler = (details) => { y: newSecondPosition.y, level: newSecondPosition.level, type: gate.type, - orientation: directionData[newDirection].rotation + orientation: directionData[newDirection].rotation, } as ModifiedLandscapeObject; const metadata = { second: JSON.parse(JSON.stringify(newSecond)), originalSecond: secondGate, main: JSON.parse(JSON.stringify(newHinge)), - originalMain: gate + originalMain: gate, }; newHinge.metadata = metadata; @@ -239,8 +237,11 @@ export default { pluginId: 'rs:gates', hooks: [ { - type: 'object_interaction', objectIds: [ 1551, 1552, 1553, 1556, 12986, 12987, 12988, 12989 ], - options: [ 'open', 'close' ], walkTo: true, handler: action - } - ] + type: 'object_interaction', + objectIds: [1551, 1552, 1553, 1556, 12986, 12987, 12988, 12989], + options: ['open', 'close'], + walkTo: true, + handler: action, + }, + ], }; diff --git a/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts b/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts index 6b4dc27c7..1c08ce3fd 100644 --- a/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts +++ b/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts @@ -1,8 +1,8 @@ import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; -import { objectIds } from '@engine/world/config/object-ids'; import { animationIds } from '@engine/world/config/animation-ids'; +import { objectIds } from '@engine/world/config/object-ids'; -export const enterDungeon: objectInteractionActionHandler = (details) => { +export const enterDungeon: objectInteractionActionHandler = details => { const loc = details.player.position.clone(); loc.y += 6400; details.player.playAnimation(animationIds.climbLadder); @@ -15,8 +15,7 @@ export const enterDungeon: objectInteractionActionHandler = (details) => { // }, World.TICK_LENGTH); }; - -export const exitDungeon: objectInteractionActionHandler = (details) => { +export const exitDungeon: objectInteractionActionHandler = details => { const loc = details.player.position.clone(); loc.y -= 6400; details.player.playAnimation(animationIds.climbLadder); @@ -29,23 +28,22 @@ export const exitDungeon: objectInteractionActionHandler = (details) => { // }, World.TICK_LENGTH); }; - export default { pluginId: 'rs:taverly_dungeon_ladder', hooks: [ { type: 'object_interaction', objectIds: objectIds.ladders.taverlyDungeonOverworld, - options: [ 'climb-down' ], + options: ['climb-down'], walkTo: true, - handler: enterDungeon + handler: enterDungeon, }, { type: 'object_interaction', objectIds: objectIds.ladders.taverlyDungeonUnderground, - options: [ 'climb-up' ], + options: ['climb-up'], walkTo: true, - handler: exitDungeon - } - ] + handler: exitDungeon, + }, + ], }; diff --git a/src/plugins/objects/item-spawns/take-axe.plugin.ts b/src/plugins/objects/item-spawns/take-axe.plugin.ts index b9be6d44c..a04463249 100644 --- a/src/plugins/objects/item-spawns/take-axe.plugin.ts +++ b/src/plugins/objects/item-spawns/take-axe.plugin.ts @@ -5,9 +5,9 @@ import { logger } from '@runejs/common'; const itemMappings: Record = { [objectIds.lumbridgeAxeInLogs]: itemIds.axes.bronze, -} +}; -export const action: objectInteractionActionHandler = (details) => { +export const action: objectInteractionActionHandler = details => { const { player, option } = details; const name = details.objectConfig.name || ''; @@ -24,7 +24,7 @@ export const action: objectInteractionActionHandler = (details) => { return; default: player.sendMessage(`This has not been implemented.`); - return + return; } }; @@ -34,9 +34,9 @@ export default { { type: 'object_interaction', objectIds: [objectIds.lumbridgeAxeInLogs], - options: [ 'take-axe' ], + options: ['take-axe'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/ladders/ladder.plugin.ts b/src/plugins/objects/ladders/ladder.plugin.ts index 2dfe4b04e..027ea400b 100644 --- a/src/plugins/objects/ladders/ladder.plugin.ts +++ b/src/plugins/objects/ladders/ladder.plugin.ts @@ -1,17 +1,17 @@ import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { ActorTask } from '@engine/task/impl/actor-task'; +import { ActorTeleportTask } from '@engine/task/impl/actor-teleport-task'; +import type { Actor } from '@engine/world/actor/actor'; import { dialogueAction } from '@engine/world/actor/player/dialogue-action'; import { Position } from '@engine/world/position'; import { logger } from '@runejs/common'; -import { ActorTeleportTask } from '@engine/task/impl/actor-teleport-task'; -import { ActorTask } from '@engine/task/impl/actor-task'; -import type { Actor } from '@engine/world/actor/actor'; const planes = { min: 0, max: 3 }; -const validate: (level: number) => boolean = (level) => { +const validate: (level: number) => boolean = level => { return planes.min <= level && level <= planes.max; }; //TODO: prevent no-clipping. -export const action: objectInteractionActionHandler = (details) => { +export const action: objectInteractionActionHandler = details => { const { player, option } = details; const ladderObjectName = details.objectConfig.name || ''; @@ -21,26 +21,28 @@ export const action: objectInteractionActionHandler = (details) => { if (option === 'climb') { dialogueAction(player) - .then(async d => d.options( - `Climb up or down the ${ladderObjectName.toLowerCase()}?`, - [ + .then(async d => + d.options(`Climb up or down the ${ladderObjectName.toLowerCase()}?`, [ `Climb up the ${ladderObjectName.toLowerCase()}.`, - `Climb down the ${ladderObjectName.toLowerCase()}.` - ])) + `Climb down the ${ladderObjectName.toLowerCase()}.`, + ]), + ) .then(d => { d.close(); switch (d.action) { case 1: case 2: - player.enqueueTask(class LadderTask extends ActorTask { - constructor(actor: Actor) { - super(actor, { repeat: false, immediate: false }); - } + player.enqueueTask( + class LadderTask extends ActorTask { + constructor(actor: Actor) { + super(actor, { repeat: false, immediate: false }); + } - execute() { - action({ ...details, option: `climb-${(d.action === 1 ? 'up' : 'down')}` }); - } - }); + execute() { + action({ ...details, option: `climb-${d.action === 1 ? 'up' : 'down'}` }); + } + }, + ); return; } }); @@ -50,12 +52,12 @@ export const action: objectInteractionActionHandler = (details) => { const { position } = player; const newPosition = new Position(position.x, position.y, position.level); newPosition.level = position.level + (up ? 1 : -1); - if(position.level === 0) { - if(newPosition.level === 1 && position.y >= 6400) { + if (position.level === 0) { + if (newPosition.level === 1 && position.y >= 6400) { newPosition.level = 0; newPosition.y -= 6414; newPosition.x++; - } else if(newPosition.level === -1) { + } else if (newPosition.level === -1) { newPosition.level = 0; newPosition.y += 6414; newPosition.x--; @@ -74,10 +76,10 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ 1738, 1739, 1740, 1746, 1747, 1748, 2147, 2148, 12964, 12965, 12966 ], - options: [ 'climb', 'climb-up', 'climb-down' ], + objectIds: [1738, 1739, 1740, 1746, 1747, 1748, 2147, 2148, 12964, 12965, 12966], + options: ['climb', 'climb-up', 'climb-down'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/mill/flour-bin.plugin.ts b/src/plugins/objects/mill/flour-bin.plugin.ts index 31e8956e9..26bf80751 100644 --- a/src/plugins/objects/mill/flour-bin.plugin.ts +++ b/src/plugins/objects/mill/flour-bin.plugin.ts @@ -1,16 +1,18 @@ -import { itemIds } from '@engine/world/config/item-ids'; +import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; -import { soundIds } from '@engine/world/config/sound-ids'; +import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; import type { Player } from '@engine/world/actor/player/player'; +import { itemIds } from '@engine/world/config/item-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; import type { ObjectConfig } from '@runejs/filestore'; -import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; -import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; -function flourBin(details: { objectConfig: ObjectConfig, player: Player }): void { +function flourBin(details: { objectConfig: ObjectConfig; player: Player }): void { const { player, objectConfig } = details; if (!details.player.savedMetadata['mill-flour']) { - player.sendMessage(`The ${(objectConfig.name || '').toLowerCase()} is already empty. You need to place wheat in the hopper upstairs `); + player.sendMessage( + `The ${(objectConfig.name || '').toLowerCase()} is already empty. You need to place wheat in the hopper upstairs `, + ); player.sendMessage(`first.`); } else { if (player.hasItemInInventory(itemIds.pot)) { @@ -26,19 +28,16 @@ function flourBin(details: { objectConfig: ObjectConfig, player: Player }): void updateBin(details); } - -export const updateBin: playerInitActionHandler = (details) => { +export const updateBin: playerInitActionHandler = details => { const count = (details.player.savedMetadata['mill-flour'] || 0) === 0 ? 0 : 1; details.player.outgoingPackets.updateClientConfig(695, count); }; - - -const actionInteract: objectInteractionActionHandler = (details) => { +const actionInteract: objectInteractionActionHandler = details => { flourBin(details); }; -const actionItem: itemOnObjectActionHandler = (details) => { +const actionItem: itemOnObjectActionHandler = details => { flourBin(details); }; @@ -47,21 +46,21 @@ export default { hooks: [ { type: 'item_on_object', - objectIds: [ 1781, 5792, 1782 ], - itemIds: [ itemIds.pot ], + objectIds: [1781, 5792, 1782], + itemIds: [itemIds.pot], walkTo: true, - handler: actionItem + handler: actionItem, }, { type: 'player_init', - handler: updateBin + handler: updateBin, }, { type: 'object_interaction', - objectIds: [ 1781, 1782], - options: [ 'empty' ], + objectIds: [1781, 1782], + options: ['empty'], walkTo: true, - handler: actionInteract - } - ] + handler: actionInteract, + }, + ], }; diff --git a/src/plugins/objects/mill/hopper-controls.plugin.ts b/src/plugins/objects/mill/hopper-controls.plugin.ts index 15a1f234f..d4997bf09 100644 --- a/src/plugins/objects/mill/hopper-controls.plugin.ts +++ b/src/plugins/objects/mill/hopper-controls.plugin.ts @@ -1,6 +1,6 @@ import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; -export const action: objectInteractionActionHandler = (details) => { +export const action: objectInteractionActionHandler = details => { details.player.busy = true; details.player.playAnimation(3571); details.player.playSound(2400, 5); @@ -23,7 +23,6 @@ export const action: objectInteractionActionHandler = (details) => { // } // details.player.busy = false; // }, World.TICK_LENGTH); - }; export default { @@ -31,10 +30,10 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ 2718, 2721 ], - options: [ 'operate' ], + objectIds: [2718, 2721], + options: ['operate'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/mill/hopper.plugin.ts b/src/plugins/objects/mill/hopper.plugin.ts index ec0f28feb..8ad78fa74 100644 --- a/src/plugins/objects/mill/hopper.plugin.ts +++ b/src/plugins/objects/mill/hopper.plugin.ts @@ -1,8 +1,8 @@ import type { itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; import { itemIds } from '@engine/world/config/item-ids'; -export const action: itemOnObjectActionHandler = (details) => { - if ((details.player.savedMetadata['mill-grain'] && details.player.savedMetadata['mill-grain'] === 1)) { +export const action: itemOnObjectActionHandler = details => { + if (details.player.savedMetadata['mill-grain'] && details.player.savedMetadata['mill-grain'] === 1) { details.player.sendMessage(`There is already grain in the hopper.`); return; } @@ -27,10 +27,10 @@ export default { hooks: [ { type: 'item_on_object', - objectIds: [ 2714, 2717 ], - itemIds: [ itemIds.grain ], + objectIds: [2714, 2717], + itemIds: [itemIds.grain], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/objects/pickables/pickables.plugin.ts b/src/plugins/objects/pickables/pickables.plugin.ts index e5540d834..8c1188a26 100644 --- a/src/plugins/objects/pickables/pickables.plugin.ts +++ b/src/plugins/objects/pickables/pickables.plugin.ts @@ -1,10 +1,9 @@ import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; -import { itemIds } from '@engine/world/config/item-ids'; import { findItem } from '@engine/config/config-handler'; +import { itemIds } from '@engine/world/config/item-ids'; import { logger } from '@runejs/common'; - -export const action: objectInteractionActionHandler = (details) => { +export const action: objectInteractionActionHandler = details => { details.player.busy = true; details.player.playAnimation(827); let itemId: number; @@ -56,10 +55,10 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ 313, 5583, 5584, 5585, 1161, 3366, 312, 2646 ], - options: [ 'pick' ], + objectIds: [313, 5583, 5584, 5585, 1161, 3366, 312, 2646], + options: ['pick'], walkTo: true, - handler: action - } - ] + handler: action, + }, + ], }; diff --git a/src/plugins/player/follow-player.plugin.js b/src/plugins/player/follow-player.plugin.js index 6ddb98538..f88e9f36b 100644 --- a/src/plugins/player/follow-player.plugin.js +++ b/src/plugins/player/follow-player.plugin.js @@ -4,7 +4,7 @@ module.exports = { { type: 'player_interaction', options: 'follow', - handler: details => details.player.follow(details.otherPlayer) - } - ] + handler: details => details.player.follow(details.otherPlayer), + }, + ], }; diff --git a/src/plugins/player/login-unlock-emotes.plugin.ts b/src/plugins/player/login-unlock-emotes.plugin.ts index 3c0cdfc5c..e489ecdfe 100644 --- a/src/plugins/player/login-unlock-emotes.plugin.ts +++ b/src/plugins/player/login-unlock-emotes.plugin.ts @@ -1,12 +1,9 @@ import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; import { unlockEmotes } from '@plugins/buttons/player-emotes.plugin'; -export const handler: playerInitActionHandler = - ({ player }) => unlockEmotes(player); +export const handler: playerInitActionHandler = ({ player }) => unlockEmotes(player); export default { pluginId: 'rs:unlock_player_emotes', - hooks: [ - { type: 'player_init', handler } - ] + hooks: [{ type: 'player_init', handler }], }; diff --git a/src/plugins/player/login-update-settings.plugin.ts b/src/plugins/player/login-update-settings.plugin.ts index 42e698dba..8cc5eb3fa 100644 --- a/src/plugins/player/login-update-settings.plugin.ts +++ b/src/plugins/player/login-update-settings.plugin.ts @@ -1,6 +1,6 @@ +import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; import { validateSettings } from '@engine/world/actor/player/player-data'; import { widgetScripts } from '@engine/world/config/widget'; -import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; export const handler: playerInitActionHandler = ({ player }) => { validateSettings(player); @@ -24,7 +24,5 @@ export const handler: playerInitActionHandler = ({ player }) => { export default { pluginId: 'rs:update_player_settings', - hooks: [ - { type: 'player_init', handler } - ] + hooks: [{ type: 'player_init', handler }], }; diff --git a/src/plugins/player/update-friends-list.plugin.ts b/src/plugins/player/update-friends-list.plugin.ts index 50723e57b..af1f7448d 100644 --- a/src/plugins/player/update-friends-list.plugin.ts +++ b/src/plugins/player/update-friends-list.plugin.ts @@ -1,5 +1,5 @@ -import { PrivateMessaging } from '@engine/world/actor/player/private-messaging'; import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; +import { PrivateMessaging } from '@engine/world/actor/player/private-messaging'; export const handler: playerInitActionHandler = ({ player }) => { PrivateMessaging.playerLoggedIn(player); @@ -8,7 +8,5 @@ export const handler: playerInitActionHandler = ({ player }) => { export default { pluginId: 'rs:update_friends_list', - hooks: [ - { type: 'player_init', handler } - ] + hooks: [{ type: 'player_init', handler }], }; diff --git a/src/plugins/quests/cooks-assistant-quest.plugin.ts b/src/plugins/quests/cooks-assistant-quest.plugin.ts index 0fe6f0294..2391b6fde 100644 --- a/src/plugins/quests/cooks-assistant-quest.plugin.ts +++ b/src/plugins/quests/cooks-assistant-quest.plugin.ts @@ -1,194 +1,224 @@ -import type { DialogueTree } from '@engine/world/actor/dialogue'; -import { dialogue, Emote, execute, goto } from '@engine/world/actor/dialogue'; -import { itemIds } from '@engine/world/config/item-ids'; +import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; import type { PlayerQuest, QuestJournalHandler } from '@engine/config/quest-config'; +import type { DialogueTree } from '@engine/world/actor/dialogue'; +import { Emote, dialogue, execute, goto } from '@engine/world/actor/dialogue'; import type { Player } from '@engine/world/actor/player/player'; import { Quest } from '@engine/world/actor/player/quest'; -import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; - +import { itemIds } from '@engine/world/config/item-ids'; const journalHandler: QuestJournalHandler = { - 0: `I can start this quest by speaking to the Cook in the Kitchen on the ground floor of Lumbridge Castle.`, 50: player => { - let questLog = `It's the Duke of Lumbridge's birthday and I have to help ` + + let questLog = + `It's the Duke of Lumbridge's birthday and I have to help ` + `his Cook make him a birthday cake. To do this I need to ` + `bring him the following ingredients:\n`; const quest = player.getQuest('rs:cooks_assistant'); - if(player.hasItemInInventory(itemIds.bucketOfMilk) || quest.metadata.givenMilk) { + if (player.hasItemInInventory(itemIds.bucketOfMilk) || quest.metadata.givenMilk) { questLog += `I have found a bucket of milk to give to the cook.\n`; } else { - questLog += `I need to find a bucket of milk. There's a cattle field east ` + + questLog += + `I need to find a bucket of milk. There's a cattle field east ` + `of Lumbridge, I should make sure I take an empty bucket with me.\n`; } - if(player.hasItemInInventory(itemIds.potOfFlour) || quest.metadata.givenFlour) { + if (player.hasItemInInventory(itemIds.potOfFlour) || quest.metadata.givenFlour) { questLog += `I have found a pot of flour to give to the cook.\n`; } else { - questLog += `I need to find a pot of flour. There's a mill found north-` + + questLog += + `I need to find a pot of flour. There's a mill found north-` + `west of Lumbridge, I should take an empty pot with me.\n`; } - if(player.hasItemInInventory(itemIds.egg) || quest.metadata.givenEgg) { + if (player.hasItemInInventory(itemIds.egg) || quest.metadata.givenEgg) { questLog += `I have found an egg to give to the cook.\n`; } else { - questLog += `I need to find an egg. The cook normally gets his eggs from ` + + questLog += + `I need to find an egg. The cook normally gets his eggs from ` + `the Groats' farm, found just to the west of the cattle field.`; } return questLog; }, - 'complete': `It was the Duke of Lumbridge's birthday, but his cook had ` + + complete: + `It was the Duke of Lumbridge's birthday, but his cook had ` + `forgotten to buy the ingredients he needed to make him a ` + `cake. I brought the cook an egg, some flour and some milk ` + `and the cook made a delicious looking cake with them.\n\n` + `As a reward he now lets me use his high quality range ` + `which lets me burn things less whenever I wish to cook ` + `there.\n\n` + - `QUEST COMPLETE!` - + `QUEST COMPLETE!`, }; function dialogueIngredientQuestions(): Function { return (options, tag_INGREDIENT_QUESTIONS) => [ - `Where do I find some flour?`, [ - player => [ Emote.GENERIC, `Where do I find some flour?` ], - cook => [ Emote.GENERIC, `There is a Mill fairly close, go North and then West. Mill Lane Mill ` + - `is just off the road to Draynor. I usually get my flour from there.` ], - cook => [ Emote.HAPPY, `Talk to Millie, she'll help, she's a lovely girl and a fine Miller.` ], - goto('tag_INGREDIENT_QUESTIONS') + `Where do I find some flour?`, + [ + player => [Emote.GENERIC, `Where do I find some flour?`], + cook => [ + Emote.GENERIC, + `There is a Mill fairly close, go North and then West. Mill Lane Mill ` + + `is just off the road to Draynor. I usually get my flour from there.`, + ], + cook => [Emote.HAPPY, `Talk to Millie, she'll help, she's a lovely girl and a fine Miller.`], + goto('tag_INGREDIENT_QUESTIONS'), ], - `How about milk?`, [ - player => [ Emote.GENERIC, `How about milk?` ], - cook => [ Emote.GENERIC, `There is a cattle field on the other side of the river, just across ` + - `the road from Groats' Farm.` ], - cook => [ Emote.HAPPY, `Talk to Gillie Groats, she look after the Dairy Cows - ` + - `she'll tell you everything you need to know about milking cows!` ], - goto('tag_INGREDIENT_QUESTIONS') + `How about milk?`, + [ + player => [Emote.GENERIC, `How about milk?`], + cook => [Emote.GENERIC, `There is a cattle field on the other side of the river, just across ` + `the road from Groats' Farm.`], + cook => [ + Emote.HAPPY, + `Talk to Gillie Groats, she look after the Dairy Cows - ` + + `she'll tell you everything you need to know about milking cows!`, + ], + goto('tag_INGREDIENT_QUESTIONS'), ], - `And eggs? Where are they found?`, [ - player => [ Emote.GENERIC, `And eggs? Where are they found?` ], - cook => [ Emote.GENERIC, `I normally get my eggs from the Groats' farm, on the other side of ` + - `the river.` ], - cook => [ Emote.GENERIC, `But any chicken should lay eggs.` ], - goto('tag_INGREDIENT_QUESTIONS') + `And eggs? Where are they found?`, + [ + player => [Emote.GENERIC, `And eggs? Where are they found?`], + cook => [Emote.GENERIC, `I normally get my eggs from the Groats' farm, on the other side of ` + `the river.`], + cook => [Emote.GENERIC, `But any chicken should lay eggs.`], + goto('tag_INGREDIENT_QUESTIONS'), ], - `Actually, I know where to find this stuff.`, [ - player => [ Emote.GENERIC, `I've got all the information I need. Thanks.` ] - ] + `Actually, I know where to find this stuff.`, + [player => [Emote.GENERIC, `I've got all the information I need. Thanks.`]], ]; } -const startQuestAction: npcInteractionActionHandler = (details) => { +const startQuestAction: npcInteractionActionHandler = details => { const { player, npc } = details; - dialogue([ player, { npc, key: 'cook' }], [ - cook => [ Emote.WORRIED, `What am I to do?` ], - options => [ - `What's wrong?`, [], - `Can you make me a cake?`, [ - player => [ Emote.HAPPY, `You're a cook, why don't you bake me a cake?` ], - cook => [ Emote.SAD, `*sniff* Don't talk to me about cakes...` ] + dialogue( + [player, { npc, key: 'cook' }], + [ + cook => [Emote.WORRIED, `What am I to do?`], + options => [ + `What's wrong?`, + [], + `Can you make me a cake?`, + [ + player => [Emote.HAPPY, `You're a cook, why don't you bake me a cake?`], + cook => [Emote.SAD, `*sniff* Don't talk to me about cakes...`], + ], + `You don't look very happy.`, + [ + player => [Emote.WORRIED, `You don't look very happy.`], + cook => [ + Emote.SAD, + `No, I'm not. The world is caving in around me - I am overcome by dark feelings ` + `of impending doom.`, + ], + options => [ + `What's wrong?`, + [], + `I'd take the rest of the day off if I were you.`, + [ + player => [Emote.GENERIC, `I'd take the rest of the day off if I were you.`], + cook => [Emote.WORRIED, `No, that's the worst thing I could do. I'd get in terrible trouble.`], + player => [Emote.SKEPTICAL, `Well maybe you need to take a holiday...`], + cook => [Emote.SAD, `That would be nice, but the Duke doesn't allow holidays for core staff.`], + player => [Emote.LAUGH, `Hmm, why not run away to the sea and start a new life as a Pirate?`], + cook => [ + Emote.SKEPTICAL, + `My wife gets sea sick, and I have an irrational fear of eyepatches. ` + `I don't see it working myself.`, + ], + player => [Emote.WORRIED, `I'm afraid I've run out of ideas.`], + cook => [Emote.SAD, `I know I'm doomed.`], + ], + ], + ], + `Nice hat!`, + [ + player => [Emote.HAPPY, `Nice hat!`], + cook => [Emote.SKEPTICAL, `Err thank you. It's a pretty ordinary cooks hat really.`], + player => [Emote.HAPPY, `Still, suits you. The trousers are pretty special too.`], + cook => [Emote.SKEPTICAL, `It's all standard cook's issue uniform...`], + player => [ + Emote.POMPOUS, + `The whole hat, apron, striped trousers ensemble - it works. It makes you ` + `look like a real cook.`, + ], + cook => [ + Emote.ANGRY, + `I am a real cook! I haven't got time to be chatting about Culinary Fashion. ` + `I am in desperate need of help!`, + ], + ], ], - `You don't look very happy.`, [ - player => [ Emote.WORRIED, `You don't look very happy.` ], - cook => [ Emote.SAD, `No, I'm not. The world is caving in around me - I am overcome by dark feelings ` + - `of impending doom.` ], - options => [ - `What's wrong?`, [], - `I'd take the rest of the day off if I were you.`, [ - player => [ Emote.GENERIC, `I'd take the rest of the day off if I were you.` ], - cook => [ Emote.WORRIED, `No, that's the worst thing I could do. I'd get in terrible trouble.` ], - player => [ Emote.SKEPTICAL, `Well maybe you need to take a holiday...` ], - cook => [ Emote.SAD, `That would be nice, but the Duke doesn't allow holidays for core staff.` ], - player => [ Emote.LAUGH, `Hmm, why not run away to the sea and start a new life as a Pirate?` ], - cook => [ Emote.SKEPTICAL, `My wife gets sea sick, and I have an irrational fear of eyepatches. ` + - `I don't see it working myself.` ], - player => [ Emote.WORRIED, `I'm afraid I've run out of ideas.` ], - cook => [ Emote.SAD, `I know I'm doomed.` ] - ] - ] + player => [Emote.HAPPY, `What's wrong?`], + cook => [ + Emote.WORRIED, + `Oh dear, oh dear, oh dear, I'm in a terrible terrible ` + + ` mess! It's the Duke's birthday today, and I should be making him a lovely big birthday cake.`, ], - `Nice hat!`, [ - player => [ Emote.HAPPY, `Nice hat!` ], - cook => [ Emote.SKEPTICAL, `Err thank you. It's a pretty ordinary cooks hat really.` ], - player => [ Emote.HAPPY, `Still, suits you. The trousers are pretty special too.` ], - cook => [ Emote.SKEPTICAL, `It's all standard cook's issue uniform...` ], - player => [ Emote.POMPOUS, `The whole hat, apron, striped trousers ensemble - it works. It makes you ` + - `look like a real cook.` ], - cook => [ Emote.ANGRY, `I am a real cook! I haven't got time to be chatting about Culinary Fashion. ` + - `I am in desperate need of help!` ] - ] - ], - player => [ Emote.HAPPY, `What's wrong?` ], - cook => [ Emote.WORRIED, `Oh dear, oh dear, oh dear, I'm in a terrible terrible ` + - ` mess! It's the Duke's birthday today, and I should be making him a lovely big birthday cake.` ], - cook => [ Emote.WORRIED, `I've forgotten to buy the ingredients. I'll never get ` + - `them in time now. He'll sack me! What will I do? I have four children and a goat to ` + - `look after. Would you help me? Please?` ], - options => [ - `I'm always happy to help a cook in distress.`, [ - execute(() => { - player.setQuestProgress('rs:cooks_assistant', 50); - }), - player => [ Emote.GENERIC, `Yes, I'll help you.` ], - cook => [ Emote.HAPPY, `Oh thank you, thank you. I need milk, an egg and flour. I'd be very grateful ` + - `if you can get them for me.` ], - player => [ Emote.GENERIC, `So where do I find these ingredients then?` ], - dialogueIngredientQuestions() + cook => [ + Emote.WORRIED, + `I've forgotten to buy the ingredients. I'll never get ` + + `them in time now. He'll sack me! What will I do? I have four children and a goat to ` + + `look after. Would you help me? Please?`, + ], + options => [ + `I'm always happy to help a cook in distress.`, + [ + execute(() => { + player.setQuestProgress('rs:cooks_assistant', 50); + }), + player => [Emote.GENERIC, `Yes, I'll help you.`], + cook => [ + Emote.HAPPY, + `Oh thank you, thank you. I need milk, an egg and flour. I'd be very grateful ` + `if you can get them for me.`, + ], + player => [Emote.GENERIC, `So where do I find these ingredients then?`], + dialogueIngredientQuestions(), + ], + `I can't right now, maybe later.`, + [ + player => [Emote.GENERIC, `No, I don't feel like it. Maybe later.`], + cook => [Emote.ANGRY, `Fine. I always knew you Adventurer types were callous beasts. ` + `Go on your merry way!`], + ], ], - `I can't right now, maybe later.`, [ - player => [ Emote.GENERIC, `No, I don't feel like it. Maybe later.` ], - cook => [ Emote.ANGRY, `Fine. I always knew you Adventurer types were callous beasts. ` + - `Go on your merry way!` ] - ] - ] - ]); + ], + ); }; function youStillNeed(quest: PlayerQuest): DialogueTree { return [ - text => `You still need to get\n` + + text => + `You still need to get\n` + `${!quest.metadata.givenMilk ? `A bucket of milk. ` : ``}${!quest.metadata.givenFlour ? `A pot of flour. ` : ``}${!quest.metadata.givenEgg ? `An egg.` : ``}`, options => [ - `I'll get right on it.`, [ - player => [Emote.GENERIC, `I'll get right on it.`] - ], - `Can you remind me how to find these things again?`, [ - player => [Emote.GENERIC, `So where do I find these ingredients then?`], - dialogueIngredientQuestions() - ] - ] + `I'll get right on it.`, + [player => [Emote.GENERIC, `I'll get right on it.`]], + `Can you remind me how to find these things again?`, + [player => [Emote.GENERIC, `So where do I find these ingredients then?`], dialogueIngredientQuestions()], + ], ]; } -const handInIngredientsAction: npcInteractionActionHandler = async (details) => { +const handInIngredientsAction: npcInteractionActionHandler = async details => { const { player, npc } = details; - const dialogueTree: DialogueTree = [ - cook => [Emote.GENERIC, `How are you getting on with finding the ingredients?`] - ]; + const dialogueTree: DialogueTree = [cook => [Emote.GENERIC, `How are you getting on with finding the ingredients?`]]; const quest = player.getQuest('rs:cooks_assistant'); const ingredients = [ { itemId: itemIds.bucketOfMilk, text: `Here's a bucket of milk.`, attr: 'givenMilk' }, { itemId: itemIds.potOfFlour, text: `Here's a pot of flour.`, attr: 'givenFlour' }, - { itemId: itemIds.egg, text: `Here's a fresh egg.`, attr: 'givenEgg' } + { itemId: itemIds.egg, text: `Here's a fresh egg.`, attr: 'givenEgg' }, ]; - for(const ingredient of ingredients) { - if(quest.metadata[ingredient.attr]) { + for (const ingredient of ingredients) { + if (quest.metadata[ingredient.attr]) { quest.metadata.ingredientCount++; continue; } - if(!player.hasItemInInventory(ingredient.itemId)) { + if (!player.hasItemInInventory(ingredient.itemId)) { continue; } @@ -197,10 +227,10 @@ const handInIngredientsAction: npcInteractionActionHandler = async (details) => execute(() => { const quest = player.getQuest('rs:cooks_assistant'); - if(player.removeFirstItem(ingredient.itemId) !== -1) { + if (player.removeFirstItem(ingredient.itemId) !== -1) { quest.metadata[ingredient.attr] = true; } - }) + }), ); } @@ -208,12 +238,13 @@ const handInIngredientsAction: npcInteractionActionHandler = async (details) => dialogueTree.push( goto(() => { - const count = [ quest.metadata.givenMilk, quest.metadata.givenFlour, quest.metadata.givenEgg ] - .filter(value => value === true).length; + const count = [quest.metadata.givenMilk, quest.metadata.givenFlour, quest.metadata.givenEgg].filter( + value => value === true, + ).length; - if(count === 3) { + if (count === 3) { return 'tag_ALL_INGREDIENTS'; - } else if(count === 0) { + } else if (count === 0) { return 'tag_NO_INGREDIENTS'; } else { return 'tag_SOME_INGREDIENTS'; @@ -227,24 +258,29 @@ const handInIngredientsAction: npcInteractionActionHandler = async (details) => cook => [Emote.SKEPTICAL, `Maybe, but I won't be holding my breath.`], execute(() => { questComplete = true; - }) + }), ], (subtree, tag_NO_INGREDIENTS) => [ player => [Emote.GENERIC, `I haven't got any of them yet, I'm still looking.`], - cook => [Emote.SAD, `Please get the ingredients quickly. I'm running out of time! ` + - `The Duke will throw me into the streets!`], - ...youStillNeed(quest) + cook => [ + Emote.SAD, + `Please get the ingredients quickly. I'm running out of time! ` + `The Duke will throw me into the streets!`, + ], + ...youStillNeed(quest), ], (subtree, tag_SOME_INGREDIENTS) => [ - cook => [Emote.SAD, `Thanks for the ingredients you have got so far, please get the rest quickly. ` + - `I'm running out of time! The Duke will throw me into the streets!`], - ...youStillNeed(quest) - ] + cook => [ + Emote.SAD, + `Thanks for the ingredients you have got so far, please get the rest quickly. ` + + `I'm running out of time! The Duke will throw me into the streets!`, + ], + ...youStillNeed(quest), + ], ); - await dialogue([ player, { npc, key: 'cook' }], dialogueTree); + await dialogue([player, { npc, key: 'cook' }], dialogueTree); - if(questComplete) { + if (questComplete) { player.setQuestProgress('rs:cooks_assistant', 'complete'); } }; @@ -260,39 +296,38 @@ export default { journalHandler, onComplete: { questCompleteWidget: { - rewardText: [ '300 Cooking XP' ], + rewardText: ['300 Cooking XP'], itemId: 1891, modelZoom: 240, modelRotationX: 180, - modelRotationY: 180 + modelRotationY: 180, }, - giveRewards: (player: Player): void => - player.skills.cooking.addExp(300) - } - }) + giveRewards: (player: Player): void => player.skills.cooking.addExp(300), + }, + }), ], hooks: [ { type: 'npc_interaction', questRequirement: { questId: 'rs:cooks_assistant', - stage: 0 + stage: 0, }, npcs: 'rs:lumbridge_castle_cook', options: 'talk-to', walkTo: true, - handler: startQuestAction + handler: startQuestAction, }, { type: 'npc_interaction', questRequirement: { questId: 'rs:cooks_assistant', - stage: 50 + stage: 50, }, npcs: 'rs:lumbridge_castle_cook', options: 'talk-to', walkTo: true, - handler: handInIngredientsAction - } - ] + handler: handInIngredientsAction, + }, + ], }; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts b/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts index 4addb3638..23217cad2 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts @@ -1,51 +1,55 @@ -import type { Player } from '@engine/world/actor/player/player'; -import { defaultPlayerTabWidgets } from '@engine/world/actor/player/player'; +import type { buttonActionHandler } from '@engine/action/pipe/button.action'; +import type { equipmentChangeActionHandler } from '@engine/action/pipe/equipment-change.action'; +import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; +import { findNpc, widgets } from '@engine/config/config-handler'; import type { QuestJournalHandler } from '@engine/config/quest-config'; import { questDialogueActionFactory } from '@engine/config/quest-config'; -import { serverConfig } from '@server/game/game-server'; -import { v4 } from 'uuid'; -import { Position } from '@engine/world/position'; +import { tabIndex } from '@engine/interface/interface-state'; +import { activeWorld } from '@engine/world'; +import { dialogue } from '@engine/world/actor/dialogue'; +import type { Player } from '@engine/world/actor/player/player'; +import { defaultPlayerTabWidgets } from '@engine/world/actor/player/player'; +import { Quest } from '@engine/world/actor/player/quest'; import { WorldInstance } from '@engine/world/instances'; -import { findNpc, widgets } from '@engine/config/config-handler'; +import { Position } from '@engine/world/position'; import { updateCombatStyleWidget } from '@plugins/combat/combat-styles.plugin'; +import { serverConfig } from '@server/game/game-server'; import { Subject } from 'rxjs'; -import { dialogue } from '@engine/world/actor/dialogue'; import { take } from 'rxjs/operators'; -import { runescapeGuideDialogueHandler } from './runescape-guide-dialogue'; +import { v4 } from 'uuid'; import { harlanDialogueHandler } from './melee-tutor-dialogue'; +import { runescapeGuideDialogueHandler } from './runescape-guide-dialogue'; import { goblinDiplomacyStageHandler } from './stage-handler'; -import { Quest } from '@engine/world/actor/player/quest'; -import { activeWorld } from '@engine/world'; -import type { buttonActionHandler } from '@engine/action/pipe/button.action'; -import type { equipmentChangeActionHandler } from '@engine/action/pipe/equipment-change.action'; -import type { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; -import { tabIndex } from '@engine/interface/interface-state'; - export const tutorialTabWidgetOrder = [ - [ tabIndex['settings'], widgets.settingsTab ], - [ tabIndex['friends'], widgets.friendsList ], - [ tabIndex['ignores'], widgets.ignoreList ], - [ tabIndex['emotes'], widgets.emotesTab ], - [ tabIndex['music'], widgets.musicPlayerTab ], - [ tabIndex['inventory'], widgets.inventory.widgetId ], - [ tabIndex['skills'], widgets.skillsTab ], - [ tabIndex['equipment'], widgets.equipment.widgetId ], - [ tabIndex['combat'], -1 ], + [tabIndex['settings'], widgets.settingsTab], + [tabIndex['friends'], widgets.friendsList], + [tabIndex['ignores'], widgets.ignoreList], + [tabIndex['emotes'], widgets.emotesTab], + [tabIndex['music'], widgets.musicPlayerTab], + [tabIndex['inventory'], widgets.inventory.widgetId], + [tabIndex['skills'], widgets.skillsTab], + [tabIndex['equipment'], widgets.equipment.widgetId], + [tabIndex['combat'], -1], // @TODO prayer, magic, ]; -export function showTabWidgetHint(player: Player, tabIndex: number, availableTabs: number, finalProgress: number, helpTitle: string, helpText: string): void { +export function showTabWidgetHint( + player: Player, + tabIndex: number, + availableTabs: number, + finalProgress: number, + helpTitle: string, + helpText: string, +): void { const tabClickEvent = { tabIndex, - event: new Subject() + event: new Subject(), }; player.metadata.tabClickEvent = tabClickEvent; - dialogue([ player ], [ - titled => [ helpTitle, helpText ] - ], { - permanent: true + dialogue([player], [titled => [helpTitle, helpText]], { + permanent: true, }); unlockAvailableTabs(player, availableTabs); @@ -62,30 +66,30 @@ export function showTabWidgetHint(player: Player, tabIndex: number, availableTab export function unlockAvailableTabs(player: Player, availableTabs?: number): void { let doCombatStyleTab = false; - if(availableTabs === undefined) { + if (availableTabs === undefined) { availableTabs = tutorialTabWidgetOrder.length; } - for(let i = 0; i < availableTabs; i++) { - if(tutorialTabWidgetOrder[i][1] === -1) { + for (let i = 0; i < availableTabs; i++) { + if (tutorialTabWidgetOrder[i][1] === -1) { doCombatStyleTab = true; } player.setSidebarWidget(tutorialTabWidgetOrder[i][0], tutorialTabWidgetOrder[i][1]); } - if(doCombatStyleTab) { + if (doCombatStyleTab) { updateCombatStyleWidget(player); } } export function npcHint(player: Player, npcKey: string | number): void { - if(typeof npcKey === 'string') { + if (typeof npcKey === 'string') { const npc = findNpc(npcKey); npcKey = npc.gameId; } const npc = activeWorld.findNpcsById(npcKey, player.instance.instanceId)[0] || null; - if(npc) { + if (npc) { player.outgoingPackets.showNpcHintIcon(npc); } } @@ -94,7 +98,7 @@ export const startTutorial = async (player: Player): Promise => { player.setQuestProgress('tyn:goblin_diplomacy', 0); defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { - if(widgetId !== -1) { + if (widgetId !== -1) { player.outgoingPackets.sendTabWidget(tabIndex, widgetId === widgets.logoutTab ? widgetId : null); } }); @@ -107,14 +111,12 @@ export const startTutorial = async (player: Player): Promise => { player.inventory.add('rs:coins'); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - await dialogue([ player ], [ - titled => [ `Getting Started`, `\nCreate your character!` ] - ], { - permanent: true + await dialogue([player], [titled => [`Getting Started`, `\nCreate your character!`]], { + permanent: true, }); player.interfaceState.openWidget(widgets.characterDesign, { - slot: 'screen' + slot: 'screen', }); await player.interfaceState.widgetClosed('screen'); @@ -122,25 +124,23 @@ export const startTutorial = async (player: Player): Promise => { export async function spawnGoblinBoi(player: Player, spawnPoint: 'beginning' | 'end'): Promise { const nearbyGoblins = activeWorld.findNpcsByKey('rs:goblin', player.instance.instanceId); - if(nearbyGoblins && nearbyGoblins.length > 0) { + if (nearbyGoblins && nearbyGoblins.length > 0) { // Goblin is already spawned, do nothing return; } // Spawn the goblin where it needs to be :) - if(spawnPoint === 'beginning') { + if (spawnPoint === 'beginning') { //const goblin = await world.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', // 0, player.instance.instanceId); - const goblin = await activeWorld.spawnNpc('rs:goblin', new Position(3221, 3257), 'SOUTH', - 0, player.instance.instanceId); + const goblin = await activeWorld.spawnNpc('rs:goblin', new Position(3221, 3257), 'SOUTH', 0, player.instance.instanceId); goblin.pathfinding.walkTo(new Position(3219, 3246), { pathingSearchRadius: 16, - ignoreDestination: false + ignoreDestination: false, }); } else { - await activeWorld.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', - 0, player.instance.instanceId); + await activeWorld.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', 0, player.instance.instanceId); } } @@ -149,12 +149,12 @@ export async function tutorialHandler(player: Player): Promise { const handler = goblinDiplomacyStageHandler[progress]; defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { - if(widgetId !== -1) { + if (widgetId !== -1) { player.setSidebarWidget(tabIndex, widgetId === widgets.logoutTab ? widgetId : null); } }); - if(handler) { + if (handler) { player.outgoingPackets.resetNpcHintIcon(); await handler(player); } @@ -166,14 +166,14 @@ function spawnQuestNpcs(player: Player): void { } const tutorialInitAction: playerInitActionHandler = async ({ player }) => { - if(serverConfig.tutorialEnabled && !player.savedMetadata.tutorialComplete) { + if (serverConfig.tutorialEnabled && !player.savedMetadata.tutorialComplete) { player.instance = new WorldInstance(v4()); player.metadata.blockObjectInteractions = true; spawnQuestNpcs(player); await tutorialHandler(player); } else { defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { - if(widgetId !== -1) { + if (widgetId !== -1) { player.setSidebarWidget(tabIndex, widgetId); } }); @@ -183,12 +183,11 @@ const tutorialInitAction: playerInitActionHandler = async ({ player }) => { const trainingSwordEquipAction: equipmentChangeActionHandler = async ({ player, itemDetails }) => { const progress = player.getQuest('tyn:goblin_diplomacy').progress; - if(progress === 85) { + if (progress === 85) { const swordEquipped = player.isItemEquipped('rs:training_sword'); const shieldEquipped = player.isItemEquipped('rs:training_shield'); - if((itemDetails.key === 'rs:training_sword' && shieldEquipped) || - (itemDetails.key === 'rs:training_shield' && swordEquipped)) { + if ((itemDetails.key === 'rs:training_sword' && shieldEquipped) || (itemDetails.key === 'rs:training_shield' && swordEquipped)) { player.setQuestProgress('tyn:goblin_diplomacy', 90); await tutorialHandler(player); } @@ -200,12 +199,9 @@ const createCharacterAction: buttonActionHandler = ({ player }): void => { }; const journalHandler: QuestJournalHandler = { - - 0: `stinkyu hoomsn HAHA\n\n\nf1nglewuRt` - + 0: `stinkyu hoomsn HAHA\n\n\nf1nglewuRt`, }; - const QUEST_ID = 'tyn:goblin_diplomacy'; const QUEST = new Quest({ @@ -216,51 +212,50 @@ const QUEST = new Quest({ journalHandler, onComplete: { questCompleteWidget: { - rewardText: [ 'A training sword & shield' ], + rewardText: ['A training sword & shield'], itemId: 9703, modelZoom: 200, modelRotationX: 0, - modelRotationY: 180 - } - } + modelRotationY: 180, + }, + }, }); - /** * Custom Goblin Diplomacy tutorial quest! */ export default { pluginId: 'tyn:goblin_diplomacy_quest', - quests: [ QUEST ], + quests: [QUEST], hooks: [ { type: 'player_init', - handler: tutorialInitAction + handler: tutorialInitAction, }, { type: 'npc_interaction', handler: questDialogueActionFactory(QUEST_ID, runescapeGuideDialogueHandler, tutorialHandler), npcs: 'rs:runescape_guide', options: 'talk-to', - walkTo: true + walkTo: true, }, { type: 'npc_interaction', handler: questDialogueActionFactory(QUEST_ID, harlanDialogueHandler, tutorialHandler), npcs: 'rs:melee_combat_tutor', options: 'talk-to', - walkTo: true + walkTo: true, }, { type: 'equipment_change', eventType: 'equip', handler: trainingSwordEquipAction, - itemIds: [ 9703, 9704 ] + itemIds: [9703, 9704], }, { type: 'button', widgetId: widgets.characterDesign, - handler: createCharacterAction - } - ] + handler: createCharacterAction, + }, + ], }; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/melee-tutor-dialogue.ts b/src/plugins/quests/goblin-diplomacy-tutorial/melee-tutor-dialogue.ts index fa08da23c..26edc6228 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/melee-tutor-dialogue.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/melee-tutor-dialogue.ts @@ -1,71 +1,91 @@ -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; import type { QuestDialogueHandler } from '@engine/config/quest-config'; - +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; export const harlanDialogueHandler: QuestDialogueHandler = { 50: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Greetings, adventurer. How can I assist you?` ], - player => [ Emote.WONDERING, `The guide in there said you could unlock my inventory and stuff.` ], - harlan => [ Emote.LAUGH, `I suppose I could, yes. But where's the fun in that?` ], - player => [ Emote.SAD, `I just want to fight something.` ], - harlan => [ Emote.GENERIC, `I'm sure you'll get the chance, what with all the recent goblin attacks on this side of the River Lum.` ], - harlan => [ Emote.GENERIC, `To that end, let me show you your inventory.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 55); - }) - ]); + await dialogue( + [player, { npc, key: 'harlan' }], + [ + harlan => [Emote.GENERIC, `Greetings, adventurer. How can I assist you?`], + player => [Emote.WONDERING, `The guide in there said you could unlock my inventory and stuff.`], + harlan => [Emote.LAUGH, `I suppose I could, yes. But where's the fun in that?`], + player => [Emote.SAD, `I just want to fight something.`], + harlan => [ + Emote.GENERIC, + `I'm sure you'll get the chance, what with all the recent goblin attacks on this side of the River Lum.`, + ], + harlan => [Emote.GENERIC, `To that end, let me show you your inventory.`], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 55); + }), + ], + ); }, 55: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Speak with me once you've opened your inventory.` ] - ]); + await dialogue([player, { npc, key: 'harlan' }], [harlan => [Emote.GENERIC, `Speak with me once you've opened your inventory.`]]); }, 60: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - player => [ Emote.SAD, `Doesn't look like I had much on me...` ], - harlan => [ Emote.GENERIC, `I would say the goblins likely ran through your pockets before the Guard hauled you in.` ], - harlan => [ Emote.GENERIC, `Lets check out your hitpoints and make sure you're in proper shape after that.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 65); - }) - ]); + await dialogue( + [player, { npc, key: 'harlan' }], + [ + player => [Emote.SAD, `Doesn't look like I had much on me...`], + harlan => [Emote.GENERIC, `I would say the goblins likely ran through your pockets before the Guard hauled you in.`], + harlan => [Emote.GENERIC, `Lets check out your hitpoints and make sure you're in proper shape after that.`], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 65); + }), + ], + ); }, 65: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Click on your skills tab to view your hitpoints stat. It should be blinking over near your inventory.` ] - ]); + await dialogue( + [player, { npc, key: 'harlan' }], + [ + harlan => [ + Emote.GENERIC, + `Click on your skills tab to view your hitpoints stat. It should be blinking over near your inventory.`, + ], + ], + ); }, 70: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `You appear to be in good shape. Though with a backpack like that, ` + - `I don't think you'll make much headway against those goblins...` ], - harlan => [ Emote.GENERIC, `I'll provide you with some starter equipment - but from there, you're on your own.` ], - harlan => [ Emote.GENERIC, `But before I can do that, you'll need to open your Equipment tab.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 75); - }) - ]); + await dialogue( + [player, { npc, key: 'harlan' }], + [ + harlan => [ + Emote.GENERIC, + `You appear to be in good shape. Though with a backpack like that, ` + + `I don't think you'll make much headway against those goblins...`, + ], + harlan => [Emote.GENERIC, `I'll provide you with some starter equipment - but from there, you're on your own.`], + harlan => [Emote.GENERIC, `But before I can do that, you'll need to open your Equipment tab.`], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 75); + }), + ], + ); }, 75: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Speak with me once you've opened your equipment.` ] - ]); + await dialogue([player, { npc, key: 'harlan' }], [harlan => [Emote.GENERIC, `Speak with me once you've opened your equipment.`]]); }, 80: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Have this training equipment and try it on.` ], - execute(() => { - player.inventory.add('rs:training_sword'); - player.inventory.add('rs:training_shield'); - player.setQuestProgress('tyn:goblin_diplomacy', 85); - }), - text => `Harlan hands you a Training sword and shield.` - ]); + await dialogue( + [player, { npc, key: 'harlan' }], + [ + harlan => [Emote.GENERIC, `Have this training equipment and try it on.`], + execute(() => { + player.inventory.add('rs:training_sword'); + player.inventory.add('rs:training_shield'); + player.setQuestProgress('tyn:goblin_diplomacy', 85); + }), + text => `Harlan hands you a Training sword and shield.`, + ], + ); }, 85: async (player, npc) => { - await dialogue([ player, { npc, key: 'harlan' } ], [ - harlan => [ Emote.GENERIC, `Try on the Training sword and shield and we can continue.` ] - ]); - } + await dialogue( + [player, { npc, key: 'harlan' }], + [harlan => [Emote.GENERIC, `Try on the Training sword and shield and we can continue.`]], + ); + }, }; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts b/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts index 5d1073275..f2ea2f1e0 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts @@ -1,103 +1,130 @@ +import type { QuestDialogueHandler } from '@engine/config/quest-config'; +import { Emote, dialogue, execute } from '@engine/world/actor/dialogue'; import type { Player } from '@engine/world/actor/player/player'; import { defaultPlayerTabWidgets } from '@engine/world/actor/player/player'; -import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; import { updateCombatStyleWidget } from '@plugins/combat/combat-styles.plugin'; -import type { QuestDialogueHandler } from '@engine/config/quest-config'; - export const runescapeGuideDialogueHandler: QuestDialogueHandler = { 5: async (player: Player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, `Greetings adventurer, welcome to RuneScape.` ], - player => [ Emote.SKEPTICAL, `How did I get here?...` ], - guide => [ Emote.GENERIC, `Seems like a goblin smacked you over the head on your way in. Nasty little things.` ], - player => [ Emote.DROWZY, `I guess that explains the headache.` ], - guide => [ Emote.GENERIC, `I would imagine so. Now, it's my job here is to show new players around.` ], - options => [ - `Go on.`, [ - player => [ Emote.GENERIC, `Carry on then.` ], - guide => [ Emote.GENERIC, `We'll start with the Options menu. Click on the blinking spanner icon at the bottom right of your game screen.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 10); - }) + await dialogue( + [player, { npc, key: 'guide' }], + [ + guide => [Emote.GENERIC, `Greetings adventurer, welcome to RuneScape.`], + player => [Emote.SKEPTICAL, `How did I get here?...`], + guide => [Emote.GENERIC, `Seems like a goblin smacked you over the head on your way in. Nasty little things.`], + player => [Emote.DROWZY, `I guess that explains the headache.`], + guide => [Emote.GENERIC, `I would imagine so. Now, it's my job here is to show new players around.`], + options => [ + `Go on.`, + [ + player => [Emote.GENERIC, `Carry on then.`], + guide => [ + Emote.GENERIC, + `We'll start with the Options menu. Click on the blinking spanner icon at the bottom right of your game screen.`, + ], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 10); + }), + ], + `I know how the game works already.`, + [ + player => [Emote.HAPPY, `This isn't my first time here, I'm good.`], + guide => [Emote.HAPPY, `Oh good, I won't tell you what you already know then.`], + execute(() => { + player.savedMetadata.tutorialComplete = true; + player.setQuestProgress('tyn:goblin_diplomacy', 'complete'); + player.instance = null; + defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { + if (widgetId !== -1) { + player.setSidebarWidget(tabIndex, widgetId); + } + }); + updateCombatStyleWidget(player); + player.metadata.blockObjectInteractions = false; + }), + ], ], - `I know how the game works already.`, [ - player => [ Emote.HAPPY, `This isn't my first time here, I'm good.` ], - guide => [ Emote.HAPPY, `Oh good, I won't tell you what you already know then.` ], - execute(() => { - player.savedMetadata.tutorialComplete = true; - player.setQuestProgress('tyn:goblin_diplomacy', 'complete'); - player.instance = null; - defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { - if(widgetId !== -1) { - player.setSidebarWidget(tabIndex, widgetId); - } - }); - updateCombatStyleWidget(player); - player.metadata.blockObjectInteractions = false; - }) - ] - ] - ]); + ], + ); }, 10: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, 'Please click on the blinking spanner icon, then we can continue.' ] - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [guide => [Emote.GENERIC, 'Please click on the blinking spanner icon, then we can continue.']], + ); }, 15: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.HAPPY, `Next we'll move on to the more social side of things. Click on the blinking icon to learn about the Friends List.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 20); - }) - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [ + guide => [ + Emote.HAPPY, + `Next we'll move on to the more social side of things. Click on the blinking icon to learn about the Friends List.`, + ], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 20); + }), + ], + ); }, 20: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, `Please return to me once you've gone through all three social tabs.` ] - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [guide => [Emote.GENERIC, `Please return to me once you've gone through all three social tabs.`]], + ); }, 25: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, `Please return to me once you've gone through all three social tabs.` ] - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [guide => [Emote.GENERIC, `Please return to me once you've gone through all three social tabs.`]], + ); }, 30: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, `Please return to me once you've gone through all three social tabs.` ] - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [guide => [Emote.GENERIC, `Please return to me once you've gone through all three social tabs.`]], + ); }, 35: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - player => [ Emote.HAPPY, `I've gone through the Friends List and everything. When do I get to kill things?` ], - guide => [ Emote.LAUGH, `All in good time, ${player.username}. We've a little more to discuss yet - like music!` ], - player => [ Emote.SKEPTICAL, `Music? Doesn't everyone turn that off?` ], - guide => [ Emote.SAD, `Some people find it nostalgic.` ], - player => [ Emote.SAD, `Sorry, go on...` ], - guide => [ Emote.GENERIC, `Yes... As I was saying... Music can be accessed from the music tab.`], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 40); - }) - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [ + player => [Emote.HAPPY, `I've gone through the Friends List and everything. When do I get to kill things?`], + guide => [Emote.LAUGH, `All in good time, ${player.username}. We've a little more to discuss yet - like music!`], + player => [Emote.SKEPTICAL, `Music? Doesn't everyone turn that off?`], + guide => [Emote.SAD, `Some people find it nostalgic.`], + player => [Emote.SAD, `Sorry, go on...`], + guide => [Emote.GENERIC, `Yes... As I was saying... Music can be accessed from the music tab.`], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 40); + }), + ], + ); }, 45: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - player => [ Emote.HAPPY, `That music tab is pretty nostalgic, I'll give ya that.` ], - guide => [ Emote.LAUGH, `Isn't it? Sometimes I can hear Harmony in my sleep.` ], - player => [ Emote.WONDERING, `So what's next?` ], - guide => [ Emote.GENERIC, `Next you'll be moving on to my friend Harlan, to learn about your inventory and skills.` ], - player => [ Emote.HAPPY, `So I finally get to kill something?` ], - guide => [ Emote.SAD, `That's all you adventurers ever want to do...` ], - guide => [ Emote.GENERIC, `Oh well. Head on over to Harlan, the melee combat tutor, and I'm sure he'll show you how to kill something.` ], - execute(() => { - player.setQuestProgress('tyn:goblin_diplomacy', 50); - }) - ]); + await dialogue( + [player, { npc, key: 'guide' }], + [ + player => [Emote.HAPPY, `That music tab is pretty nostalgic, I'll give ya that.`], + guide => [Emote.LAUGH, `Isn't it? Sometimes I can hear Harmony in my sleep.`], + player => [Emote.WONDERING, `So what's next?`], + guide => [Emote.GENERIC, `Next you'll be moving on to my friend Harlan, to learn about your inventory and skills.`], + player => [Emote.HAPPY, `So I finally get to kill something?`], + guide => [Emote.SAD, `That's all you adventurers ever want to do...`], + guide => [ + Emote.GENERIC, + `Oh well. Head on over to Harlan, the melee combat tutor, and I'm sure he'll show you how to kill something.`, + ], + execute(() => { + player.setQuestProgress('tyn:goblin_diplomacy', 50); + }), + ], + ); }, 50: async (player, npc) => { - await dialogue([ player, { npc, key: 'guide' } ], [ - guide => [ Emote.GENERIC, `Please speak to my friend Harlan, the melee combat tutor, to continue.` ] - ]); - } + await dialogue( + [player, { npc, key: 'guide' }], + [guide => [Emote.GENERIC, `Please speak to my friend Harlan, the melee combat tutor, to continue.`]], + ); + }, }; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts index c11412538..e6703bfad 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts @@ -1,17 +1,19 @@ +import { findNpc } from '@engine/config/config-handler'; +import type { QuestStageHandler } from '@engine/config/quest-config'; +import { tabIndex } from '@engine/interface/interface-state'; +import { activeWorld } from '@engine/world'; import { dialogue } from '@engine/world/actor/dialogue'; +import { Cutscene } from '@engine/world/actor/player/cutscenes'; +import { soundIds } from '@engine/world/config/sound-ids'; +import { schedule } from '@engine/world/task'; import { - tutorialHandler, - npcHint, showTabWidgetHint, spawnGoblinBoi, + npcHint, + showTabWidgetHint, + spawnGoblinBoi, startTutorial, - unlockAvailableTabs + tutorialHandler, + unlockAvailableTabs, } from '@plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin'; -import { schedule } from '@engine/world/task'; -import { findNpc } from '@engine/config/config-handler'; -import { Cutscene } from '@engine/world/actor/player/cutscenes'; -import { soundIds } from '@engine/world/config/sound-ids'; -import type { QuestStageHandler } from '@engine/config/quest-config'; -import { activeWorld } from '@engine/world'; -import { tabIndex } from '@engine/interface/interface-state'; export const goblinDiplomacyStageHandler: QuestStageHandler = { 0: async player => { @@ -22,71 +24,81 @@ export const goblinDiplomacyStageHandler: QuestStageHandler = { 5: async player => { npcHint(player, 'rs:runescape_guide'); - await dialogue([ player ], [ - titled => [ `Getting Started`, `\nWelcome to RuneScape!\nSpeak with the Guide to begin your journey.` ] - ], { - permanent: true + await dialogue([player], [titled => [`Getting Started`, `\nWelcome to RuneScape!\nSpeak with the Guide to begin your journey.`]], { + permanent: true, }); }, 10: player => { - showTabWidgetHint(player, tabIndex['settings'], 1, 15, + showTabWidgetHint( + player, + tabIndex['settings'], + 1, + 15, `Game Options`, `The Options menu can be used to modify various game settings.\n` + `Click the blinking icon to open the Options menu.\n\n` + - `When you're finished, speak with the Guide to continue.`); + `When you're finished, speak with the Guide to continue.`, + ); }, 15: player => { npcHint(player, 'rs:runescape_guide'); unlockAvailableTabs(player, 1); - dialogue([ player ], [ - titled => [ `Getting Started`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Getting Started`, `\nSpeak with the Guide to continue.`]], { + permanent: true, }); }, 20: player => { - showTabWidgetHint(player, tabIndex['friends'], 2, 25, - `Friends List`, `\nKeep track of your friends via the Friends List.`); + showTabWidgetHint(player, tabIndex['friends'], 2, 25, `Friends List`, `\nKeep track of your friends via the Friends List.`); }, 25: player => { - showTabWidgetHint(player, tabIndex['ignores'], 3, 30, + showTabWidgetHint( + player, + tabIndex['ignores'], + 3, + 30, `Ignore List`, `\nThe Ignore List allows you to block messages from other users.\n` + - `Check it out by clicking the blinking icon at the bottom right.`); + `Check it out by clicking the blinking icon at the bottom right.`, + ); }, 30: player => { - showTabWidgetHint(player, tabIndex['emotes'], 4, 35, + showTabWidgetHint( + player, + tabIndex['emotes'], + 4, + 35, `Emotes`, `Perform emotes for other players via the Emotes tab.\n\n` + - `Click on the blinking Emotes tab to see the list of emotes you can perform, then speak with the Guide to continue.`); + `Click on the blinking Emotes tab to see the list of emotes you can perform, then speak with the Guide to continue.`, + ); }, 35: player => { npcHint(player, 'rs:runescape_guide'); unlockAvailableTabs(player, 4); - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nSpeak with the Guide to continue.`]], { + permanent: true, }); }, 40: player => { - showTabWidgetHint(player, tabIndex['music'], 5, 45, + showTabWidgetHint( + player, + tabIndex['music'], + 5, + 45, `Music`, - `Check out the music tab to view and play all of your favorite RuneScape tracks!\n` + - `Once you've unlocked them, of course.`); + `Check out the music tab to view and play all of your favorite RuneScape tracks!\n` + `Once you've unlocked them, of course.`, + ); }, 45: player => { npcHint(player, 'rs:runescape_guide'); unlockAvailableTabs(player, 5); - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nSpeak with the Guide to continue.`]], { + permanent: true, }); }, 50: player => { @@ -94,77 +106,80 @@ export const goblinDiplomacyStageHandler: QuestStageHandler = { npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 5); - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Melee Combat Tutor to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nSpeak with the Melee Combat Tutor to continue.`]], { + permanent: true, }); }, 55: player => { - showTabWidgetHint(player, tabIndex['inventory'], 6, 60, + showTabWidgetHint( + player, + tabIndex['inventory'], + 6, + 60, `Inventory`, `Your inventory contains any items held on your person that aren't equipped. ` + - `Click the blinking backpack icon to open your inventory.`); + `Click the blinking backpack icon to open your inventory.`, + ); }, 60: player => { npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 6); - dialogue([ player ], [ - titled => [ `Continue`, `\nTalk-to the Melee Combat Tutor to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nTalk-to the Melee Combat Tutor to continue.`]], { + permanent: true, }); }, 65: player => { - showTabWidgetHint(player, tabIndex['skills'], 7, 70, + showTabWidgetHint( + player, + tabIndex['skills'], + 7, + 70, `Skills`, `You can see your character's skill levels on the Skills tab, including your current number of hitpoints. ` + - `If your hitpoints ever reach zero, you'll die - so be careful!`); + `If your hitpoints ever reach zero, you'll die - so be careful!`, + ); }, 70: player => { npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 7); - dialogue([ player ], [ - titled => [ `Continue`, `\nTalk-to the Melee Combat Tutor to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nTalk-to the Melee Combat Tutor to continue.`]], { + permanent: true, }); }, 75: player => { - showTabWidgetHint(player, tabIndex['equipment'], 8, 80, + showTabWidgetHint( + player, + tabIndex['equipment'], + 8, + 80, `Equipment`, `The equipment tab contains details on everything you have equipped, as well as any stat ` + - `bonuses received from your equipment.`); + `bonuses received from your equipment.`, + ); }, 80: player => { npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 8); - dialogue([ player ], [ - titled => [ `Continue`, `\nTalk-to the Melee Combat Tutor to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nTalk-to the Melee Combat Tutor to continue.`]], { + permanent: true, }); }, 85: player => { unlockAvailableTabs(player, 8); - dialogue([ player ], [ - titled => [ `Continue`, `\nEquip the Training sword and shield.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nEquip the Training sword and shield.`]], { + permanent: true, }); }, 90: async player => { npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 8); - dialogue([ player ], [ - titled => [ `Continue`, `\nTalk-to the Melee Combat Tutor to continue.` ] - ], { - permanent: true + dialogue([player], [titled => [`Continue`, `\nTalk-to the Melee Combat Tutor to continue.`]], { + permanent: true, }); // @TODO vvv this is all placeholder code for the cutscene that will be needed later :) @@ -213,5 +228,5 @@ export const goblinDiplomacyStageHandler: QuestStageHandler = { } player.playSound(soundIds.npc.human.maleDefence, 5); - } + }, }; diff --git a/src/plugins/quests/quest-journal.plugin.ts b/src/plugins/quests/quest-journal.plugin.ts index 7c2df907b..84b2e4676 100644 --- a/src/plugins/quests/quest-journal.plugin.ts +++ b/src/plugins/quests/quest-journal.plugin.ts @@ -1,37 +1,34 @@ -import { wrapText } from '@engine/util/strings'; +import type { buttonActionHandler } from '@engine/action/pipe/button.action'; import { widgets } from '@engine/config/config-handler'; -import type { Quest } from '@engine/world/actor/player/quest'; import type { QuestKey } from '@engine/config/quest-config'; -import type { buttonActionHandler } from '@engine/action/pipe/button.action'; import { questMap } from '@engine/plugins/loader'; +import { wrapText } from '@engine/util/strings'; +import type { Quest } from '@engine/world/actor/player/quest'; export const handler: buttonActionHandler = async ({ player, buttonId }) => { - const quest = Object.values(questMap) - .find(quest => quest.questTabId === buttonId); - if(!quest) { + const quest = Object.values(questMap).find(quest => quest.questTabId === buttonId); + if (!quest) { return; } - const [ playerQuest ] = player.quests.filter( - (playerQuest) => playerQuest.questId === quest.id - ); + const [playerQuest] = player.quests.filter(playerQuest => playerQuest.questId === quest.id); let playerStage: QuestKey = 0; - if(playerQuest && playerQuest.progress !== undefined) { + if (playerQuest && playerQuest.progress !== undefined) { playerStage = playerQuest.progress; } const journalHandler = quest.journalHandler[playerStage]; - if(journalHandler === undefined) { + if (journalHandler === undefined) { const questJournalStages = Object.keys(quest.journalHandler); let journalEntry; - for(const stage of questJournalStages) { + for (const stage of questJournalStages) { const stageNum = parseInt(stage, 10); - if(isNaN(stageNum) || playerStage === 'complete') { + if (isNaN(stageNum) || playerStage === 'complete') { continue; } - if(stageNum <= playerStage) { + if (stageNum <= playerStage) { journalEntry = stage; } else { break; @@ -42,43 +39,41 @@ export const handler: buttonActionHandler = async ({ player, buttonId }) => { const color = 128; let text: string = ''; - if(typeof journalHandler === 'function') { + if (typeof journalHandler === 'function') { text = await Promise.resolve(journalHandler(player)); - } else if(typeof journalHandler === 'string') { + } else if (typeof journalHandler === 'string') { text = journalHandler; } let lines: string[]; - if(text) { + if (text) { lines = wrapText(text as string, 395); } else { - lines = [ 'Invalid Quest Stage' ]; + lines = ['Invalid Quest Stage']; } player.modifyWidget(widgets.questJournal, { childId: 2, text: '@dre@' + quest.name }); - for(let i = 0; i <= 100; i++) { - if(i === 0) { + for (let i = 0; i <= 100; i++) { + if (i === 0) { player.modifyWidget(widgets.questJournal, { childId: 3, text: `${lines[0]}` }); continue; } - if(lines.length > i) { - player.modifyWidget(widgets.questJournal, { childId: (i + 4), text: `${lines[i]}` }); + if (lines.length > i) { + player.modifyWidget(widgets.questJournal, { childId: i + 4, text: `${lines[i]}` }); } else { - player.modifyWidget(widgets.questJournal, { childId: (i + 4), text: '' }); + player.modifyWidget(widgets.questJournal, { childId: i + 4, text: '' }); } } player.interfaceState.openWidget(widgets.questJournal, { slot: 'screen', - multi: false + multi: false, }); }; export default { pluginId: 'rs:quest_journal', - hooks: [ - { type: 'button', widgetId: widgets.questTab, handler } - ] + hooks: [{ type: 'button', widgetId: widgets.questTab, handler }], }; diff --git a/src/plugins/quests/witchs-potion-quest.plugin.ts b/src/plugins/quests/witchs-potion-quest.plugin.ts index 810c7e8b1..da2c6f671 100644 --- a/src/plugins/quests/witchs-potion-quest.plugin.ts +++ b/src/plugins/quests/witchs-potion-quest.plugin.ts @@ -1,15 +1,13 @@ import type { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; -import { dialogue, Emote, execute, goto } from '@engine/world/actor/dialogue'; -import { itemIds } from '@engine/world/config/item-ids'; +import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; import type { QuestJournalHandler } from '@engine/config/quest-config'; +import { Emote, dialogue, execute, goto } from '@engine/world/actor/dialogue'; import type { Player } from '@engine/world/actor/player/player'; import { Quest } from '@engine/world/actor/player/quest'; -import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { itemIds } from '@engine/world/config/item-ids'; import { Position } from '@engine/world/position'; - const journalHandler: QuestJournalHandler = { - 0: `I can start this quest by speaking to Hetty in her house in Rimmington, West of Port Sarim`, @@ -23,40 +21,40 @@ const journalHandler: QuestJournalHandler = { { itemId: itemIds.witchesPotion.ratsTail, haveText: `I have a rat's tail with me,`, - dontHaveText: `A rat's tail, I could get one from a small rat.` + dontHaveText: `A rat's tail, I could get one from a small rat.`, }, { itemId: itemIds.witchesPotion.burntMeat, haveText: `I have a piece of burnt meat with me,`, dontHaveText: `A piece of burnt meat, I could thoroughly cook a piece of - raw beef.` + raw beef.`, }, { itemId: itemIds.witchesPotion.onion, haveText: `I have an onion with me,`, - dontHaveText: `An onion, I could probably find one at a farm.` + dontHaveText: `An onion, I could probably find one at a farm.`, }, { itemId: itemIds.witchesPotion.eyeOfNewt, haveText: `I have an eye of newt with me,`, dontHaveText: `An eye of newt, maybe the Magic shop in Port Sarim would - sell me this?` - } + sell me this?`, + }, ]; let ingredientsObtained = 0; for (const ingredient of questLogIngredientData) { - questLog += `\n` + questLog += `\n`; if (player.hasItemInInventory(ingredient.itemId)) { questLog += ingredient.haveText; ingredientsObtained++; } else { - questLog += ingredient.dontHaveText + questLog += ingredient.dontHaveText; } } - if(ingredientsObtained === 4) { - questLog += `\nI should bring these ingredients to Hetty.` + if (ingredientsObtained === 4) { + questLog += `\nI should bring these ingredients to Hetty.`; } return questLog; @@ -66,51 +64,49 @@ const journalHandler: QuestJournalHandler = { and an eye of newt which she used to make a potion. I should drink from the cauldron and improve my magic!`, - - 'complete': `I brought her an onion, a rat's tail, a piece of burnt meat + complete: `I brought her an onion, a rat's tail, a piece of burnt meat and an eye of newt which she used to make a potion.\n I drank from the cauldron and my magic power increased!\n QUEST COMPLETE!`, - }; -const drinkThePotionDialogue: npcInteractionActionHandler = (details) => { +const drinkThePotionDialogue: npcInteractionActionHandler = details => { const { player, npc } = details; player.face(npc); - dialogue([player, { npc, key: 'hetty' }], [ - hetty => [Emote.ANGRY, `Well are you going to drink the potion or not?`], - player => [Emote.GENERIC, `Yes, I will.`] - ]); -} + dialogue( + [player, { npc, key: 'hetty' }], + [hetty => [Emote.ANGRY, `Well are you going to drink the potion or not?`], player => [Emote.GENERIC, `Yes, I will.`]], + ); +}; -const drinkFromCauldron: objectInteractionActionHandler = async (details) => { +const drinkFromCauldron: objectInteractionActionHandler = async details => { const { player, object } = details; let questComplete = false; - player.face(new Position(object.x, object.y)) - await dialogue([player], [ - text => (`You drink from the cauldron. It tastes horrible!\nYou feel yourself imbued with power.`), - execute(() => { - questComplete = true; - }) - ]); + player.face(new Position(object.x, object.y)); + await dialogue( + [player], + [ + text => `You drink from the cauldron. It tastes horrible!\nYou feel yourself imbued with power.`, + execute(() => { + questComplete = true; + }), + ], + ); if (questComplete) { player.setQuestProgress('rs:witchs_potion', `complete`); } -} +}; -const attemptToDrinkBeforeAllowed: objectInteractionActionHandler = async (details) => { +const attemptToDrinkBeforeAllowed: objectInteractionActionHandler = async details => { const { player, object } = details; - player.face(new Position(object.x, object.y)) - await dialogue([player], [ - player => [Emote.GENERIC, `As nice as that looks I think I'll give it a miss for now.`] - ]); -} - + player.face(new Position(object.x, object.y)); + await dialogue([player], [player => [Emote.GENERIC, `As nice as that looks I think I'll give it a miss for now.`]]); +}; -const dialogueIngredientQuestions: npcInteractionActionHandler = (details) => { +const dialogueIngredientQuestions: npcInteractionActionHandler = details => { const { player, npc } = details; const hasRatsTail = player.hasItemInInventory(itemIds.witchesPotion.ratsTail); @@ -122,159 +118,173 @@ const dialogueIngredientQuestions: npcInteractionActionHandler = (details) => { { itemId: itemIds.witchesPotion.ratsTail, haveText: `I have the rat's tail (ewww), `, - dontHaveText: `I don't have a rat's tail, ` + dontHaveText: `I don't have a rat's tail, `, }, { itemId: itemIds.witchesPotion.burntMeat, haveText: `I have the burnt meat, `, - dontHaveText: `I don't have any burnt meat, ` + dontHaveText: `I don't have any burnt meat, `, }, { itemId: itemIds.witchesPotion.onion, haveText: `I have an onion, and `, - dontHaveText: `I don't have an onion, and ` + dontHaveText: `I don't have an onion, and `, }, { itemId: itemIds.witchesPotion.eyeOfNewt, haveText: `I have the eye of newt, yum!`, - dontHaveText: `I don't have an eye of newt.` - } + dontHaveText: `I don't have an eye of newt.`, + }, ]; - let requirementsDialogue = ``; for (const ingredient of ingredients) { if (player.hasItemInInventory(ingredient.itemId)) { requirementsDialogue += ingredient.haveText; } else { - requirementsDialogue += ingredient.dontHaveText + requirementsDialogue += ingredient.dontHaveText; } } - - dialogue([player, { npc, key: 'hetty' }], [ - goto(() => { - const count = [hasRatsTail, hasEyeOfNewt, hasOnion, hasBurntMeat] - .filter(value => value === true).length; - if (count === 4) { - return 'tag_ALL_INGREDIENTS'; - } else if (count === 0) { - return 'tag_NO_INGREDIENTS'; - } else { - return 'tag_SOME_INGREDIENTS'; - } - }), - (subtree, tag_ALL_INGREDIENTS) => [ - hetty => [Emote.HAPPY, `So have you found the things for the potion?`], - player => [Emote.HAPPY, `Yes I have everything!`], - hetty => [Emote.HAPPY, `Excellent, can I have them then?`], - (text, tag_has_ingredients) => (`You pass the ingredients to Hetty and she puts them all into her cauldron. Hetty closes her eyes and begins to chant. The cauldron bubbles mysteriously.`), - player => [Emote.GENERIC, `Well, is it ready?`], - execute(() => { - player.removeFirstItem(itemIds.witchesPotion.ratsTail); - player.removeFirstItem(itemIds.witchesPotion.onion) - player.removeFirstItem(itemIds.witchesPotion.burntMeat); - player.removeFirstItem(itemIds.witchesPotion.eyeOfNewt); - player.setQuestProgress(`rs:witchs_potion`, 75); + dialogue( + [player, { npc, key: 'hetty' }], + [ + goto(() => { + const count = [hasRatsTail, hasEyeOfNewt, hasOnion, hasBurntMeat].filter(value => value === true).length; + if (count === 4) { + return 'tag_ALL_INGREDIENTS'; + } else if (count === 0) { + return 'tag_NO_INGREDIENTS'; + } else { + return 'tag_SOME_INGREDIENTS'; + } }), - hetty => [Emote.HAPPY, `Ok, now drink from the cauldron.`], - ], - (subtree, tag_NO_INGREDIENTS) => [ - player => [Emote.HAPPY, `I've been looking for those ingredients.`], - hetty => [Emote.HAPPY, `So what have you found so far?`], - player => [Emote.GENERIC, `I'm afraid I don't have any of them yet.`], - hetty => [Emote.SAD, `Well I can't make the potion without them! Remember... You need an eye of newt, a rat's tail, an onion, and a piece of burnt meat. Off you go dear!`], + (subtree, tag_ALL_INGREDIENTS) => [ + hetty => [Emote.HAPPY, `So have you found the things for the potion?`], + player => [Emote.HAPPY, `Yes I have everything!`], + hetty => [Emote.HAPPY, `Excellent, can I have them then?`], + (text, tag_has_ingredients) => + `You pass the ingredients to Hetty and she puts them all into her cauldron. Hetty closes her eyes and begins to chant. The cauldron bubbles mysteriously.`, + player => [Emote.GENERIC, `Well, is it ready?`], + execute(() => { + player.removeFirstItem(itemIds.witchesPotion.ratsTail); + player.removeFirstItem(itemIds.witchesPotion.onion); + player.removeFirstItem(itemIds.witchesPotion.burntMeat); + player.removeFirstItem(itemIds.witchesPotion.eyeOfNewt); + player.setQuestProgress(`rs:witchs_potion`, 75); + }), + hetty => [Emote.HAPPY, `Ok, now drink from the cauldron.`], + ], + (subtree, tag_NO_INGREDIENTS) => [ + player => [Emote.HAPPY, `I've been looking for those ingredients.`], + hetty => [Emote.HAPPY, `So what have you found so far?`], + player => [Emote.GENERIC, `I'm afraid I don't have any of them yet.`], + hetty => [ + Emote.SAD, + `Well I can't make the potion without them! Remember... You need an eye of newt, a rat's tail, an onion, and a piece of burnt meat. Off you go dear!`, + ], + ], + (subtree, tag_SOME_INGREDIENTS) => [ + player => [Emote.HAPPY, `I've been looking for those ingredients.`], + hetty => [Emote.HAPPY, `So what have you found so far?`], + player => [Emote.GENERIC, requirementsDialogue], + hetty => [Emote.GENERIC, `Great, but I'll need the other ingredients as well.`], + ], ], - (subtree, tag_SOME_INGREDIENTS) => [ - player => [Emote.HAPPY, `I've been looking for those ingredients.`], - hetty => [Emote.HAPPY, `So what have you found so far?`], - player => [Emote.GENERIC, requirementsDialogue], - hetty => [Emote.GENERIC, `Great, but I'll need the other ingredients as well.`], - ] - ]); -} - + ); +}; -const afterQuestDialogue: npcInteractionActionHandler = (details) => { +const afterQuestDialogue: npcInteractionActionHandler = details => { const { player, npc } = details; player.face(npc); + dialogue( + [player, { npc, key: 'hetty' }], + [ + hetty => [Emote.HAPPY, `How's your magic coming along?`], + player => [Emote.HAPPY, `I'm practicing and slowly getting better.`], + hetty => [Emote.HAPPY, `Good, good.`], + ], + ); +}; - dialogue([player, { npc, key: 'hetty' }], [ - hetty => [Emote.HAPPY, `How's your magic coming along?`], - player => [Emote.HAPPY, `I'm practicing and slowly getting better.`], - hetty => [Emote.HAPPY, `Good, good.`], - ]); -} - -const startQuestAction: npcInteractionActionHandler = async (details) => { +const startQuestAction: npcInteractionActionHandler = async details => { const { player, npc } = details; player.face(npc); npc.face(player); let beginQuest = false; - await dialogue([player, { npc, key: 'hetty' }], [ - hetty => [Emote.WONDERING, 'What could you want with an old woman like me?'], - options => [ - `I am in search of a quest.`, [ - (player, tag_search_of_quest) => [Emote.GENERIC, `I am in search of a quest.`], - hetty => [Emote.HAPPY, `Hmmm... Maybe I can think of something for you.`], - hetty => [Emote.HAPPY, `Would you like to become more proficient in the dark arts?`], - - options => [ - `Yes, help me become one with my darker side.`, [ - player => [Emote.HAPPY, `Yes, help me become one with my darker side.`], - goto(`tag_darker_side`) - ], - `No, I have my principles and honour.`, [ - player => [Emote.GENERIC, `No, I have my principles and honour.`], - hetty => [Emote.SAD, `Suit yourself, but you're missing out.`] - ], - `What, you mean improve my magic?`, [ - player => [Emote.SAD, 'What, you mean improve my magic?'], - text => (`The witch sighs.`), - hetty => [Emote.GENERIC, 'Yes, improve your magic...'], - hetty => [Emote.SAD, 'Do you have no sense of drama?'], - options => [ - `Yes, I'd like to improve my magic.`, [ - player => [Emote.GENERIC, `Yes, I'd like to improve my magic.`], - (hetty, tag_darker_side) => [Emote.HAPPY, `Okay, I'm going to make a potion to help bring out your darker self.`], - hetty => [Emote.GENERIC, `You will need certain ingredients.`], - player => [Emote.GENERIC, `What do I need?`], - execute(() => { - beginQuest = true; - }), - hetty => [Emote.WONDERING, `You need an eye of newt, a rat's tail, an onion... Oh and a piece of burnt meat.`], - player => [Emote.HAPPY, `Great, I'll go and get them.`], - ], - `No, I'm not interested.`, [ - player => [Emote.SAD, `No, I'm not interested.`], - hetty => [Emote.SAD, `Many aren't to start off with.`], - text => (`The witch smiles mysteriously.`), - hetty => [Emote.GENERIC, `But I think you'll be drawn back to this place.`] + await dialogue( + [player, { npc, key: 'hetty' }], + [ + hetty => [Emote.WONDERING, 'What could you want with an old woman like me?'], + options => [ + `I am in search of a quest.`, + [ + (player, tag_search_of_quest) => [Emote.GENERIC, `I am in search of a quest.`], + hetty => [Emote.HAPPY, `Hmmm... Maybe I can think of something for you.`], + hetty => [Emote.HAPPY, `Would you like to become more proficient in the dark arts?`], + + options => [ + `Yes, help me become one with my darker side.`, + [player => [Emote.HAPPY, `Yes, help me become one with my darker side.`], goto(`tag_darker_side`)], + `No, I have my principles and honour.`, + [ + player => [Emote.GENERIC, `No, I have my principles and honour.`], + hetty => [Emote.SAD, `Suit yourself, but you're missing out.`], + ], + `What, you mean improve my magic?`, + [ + player => [Emote.SAD, 'What, you mean improve my magic?'], + text => `The witch sighs.`, + hetty => [Emote.GENERIC, 'Yes, improve your magic...'], + hetty => [Emote.SAD, 'Do you have no sense of drama?'], + options => [ + `Yes, I'd like to improve my magic.`, + [ + player => [Emote.GENERIC, `Yes, I'd like to improve my magic.`], + (hetty, tag_darker_side) => [ + Emote.HAPPY, + `Okay, I'm going to make a potion to help bring out your darker self.`, + ], + hetty => [Emote.GENERIC, `You will need certain ingredients.`], + player => [Emote.GENERIC, `What do I need?`], + execute(() => { + beginQuest = true; + }), + hetty => [ + Emote.WONDERING, + `You need an eye of newt, a rat's tail, an onion... Oh and a piece of burnt meat.`, + ], + player => [Emote.HAPPY, `Great, I'll go and get them.`], + ], + `No, I'm not interested.`, + [ + player => [Emote.SAD, `No, I'm not interested.`], + hetty => [Emote.SAD, `Many aren't to start off with.`], + text => `The witch smiles mysteriously.`, + hetty => [Emote.GENERIC, `But I think you'll be drawn back to this place.`], + ], + `Show me the mysteries of the dark arts...`, + [player => [Emote.GENERIC, `Show me the mysteries of the dark arts...`], goto(`tag_darker_side`)], ], - `Show me the mysteries of the dark arts...`, [ - player => [Emote.GENERIC, `Show me the mysteries of the dark arts...`], - goto(`tag_darker_side`) - ] ], - ] + ], ], - ], - `I've heard that you are a witch.`, [ - player => [Emote.HAPPY, `I've heard that you are a witch.`], - hetty => [Emote.HAPPY, `Yes it does seem to be getting fairly common knowledge.`], - hetty => [Emote.WORRIED, `I fear I may get a visit from the witch hunters of Falador before long.`], - options => [ - `I am in search of a quest.`, [ - goto('tag_search_of_quest') + `I've heard that you are a witch.`, + [ + player => [Emote.HAPPY, `I've heard that you are a witch.`], + hetty => [Emote.HAPPY, `Yes it does seem to be getting fairly common knowledge.`], + hetty => [Emote.WORRIED, `I fear I may get a visit from the witch hunters of Falador before long.`], + options => [ + `I am in search of a quest.`, + [goto('tag_search_of_quest')], + `Goodbye.`, + [player => [Emote.VERY_SAD, `Goodbye.`]], ], - `Goodbye.`, [ - player => [Emote.VERY_SAD, `Goodbye.`] - ] - ] - ] - ] - ]) + ], + ], + ], + ); if (beginQuest) { player.setQuestProgress('rs:witchs_potion', 50); } @@ -295,12 +305,11 @@ export default { itemId: 221, modelZoom: 240, modelRotationX: 180, - modelRotationY: 180 + modelRotationY: 180, }, - giveRewards: (player: Player): void => - player.skills.magic.addExp(325) - } - }) + giveRewards: (player: Player): void => player.skills.magic.addExp(325), + }, + }), ], hooks: [ { @@ -308,58 +317,58 @@ export default { npcs: 'rs:hetty', options: 'talk-to', walkTo: true, - handler: startQuestAction + handler: startQuestAction, }, { type: 'npc_interaction', questRequirement: { questId: 'rs:witchs_potion', - stage: 50 + stage: 50, }, npcs: 'rs:hetty', options: 'talk-to', walkTo: true, - handler: dialogueIngredientQuestions + handler: dialogueIngredientQuestions, }, { type: 'npc_interaction', questRequirement: { questId: 'rs:witchs_potion', - stage: 75 + stage: 75, }, npcs: 'rs:hetty', options: 'talk-to', walkTo: true, - handler: drinkThePotionDialogue + handler: drinkThePotionDialogue, }, { type: 'npc_interaction', questRequirement: { questId: 'rs:witchs_potion', - stage: 'complete' + stage: 'complete', }, npcs: 'rs:hetty', options: 'talk-to', walkTo: true, - handler: afterQuestDialogue + handler: afterQuestDialogue, }, { type: 'object_interaction', objectIds: 2024, questRequirement: { questId: 'rs:witchs_potion', - stage: 75 + stage: 75, }, options: 'drink from', walkTo: true, - handler: drinkFromCauldron + handler: drinkFromCauldron, }, { type: 'object_interaction', objectIds: 2024, options: 'drink from', walkTo: true, - handler: attemptToDrinkBeforeAllowed - } - ] + handler: attemptToDrinkBeforeAllowed, + }, + ], }; diff --git a/src/plugins/skills/construction/con-constants.ts b/src/plugins/skills/construction/con-constants.ts index 23dbcd515..ff7ae2369 100644 --- a/src/plugins/skills/construction/con-constants.ts +++ b/src/plugins/skills/construction/con-constants.ts @@ -1,11 +1,9 @@ import { Position } from '@engine/world/position'; - export const MAP_SIZE = 13; - export type RoomType = - 'empty' + | 'empty' | 'empty_grass' | 'garden' | 'formal_garden' @@ -26,44 +24,41 @@ export type RoomType = | 'oubliette' | 'costume_room'; - export const RoomStyle = { basic_wood: 0, basic_stone: 1, whitewashed_stone: 2, fremennik_wood: 3, tropical_wood: 4, - fancy_stone: 5 + fancy_stone: 5, }; - /** * A map of room types to their respective world map template positions within the game. */ export const roomTemplates: { [key in RoomType]: Position } = { - empty: new Position(1856, 5056), - empty_grass: new Position(1864, 5056), - garden: new Position(1856, 5064), - formal_garden: new Position(1872, 5064), - parlor: new Position(1856, 5112), - kitchen: new Position(1872, 5112), - dining_room: new Position(1888, 5112), - bedroom: new Position(1904, 5112), - skill_hall: new Position(1864, 5104), - quest_hall: new Position(1912, 5104), + empty: new Position(1856, 5056), + empty_grass: new Position(1864, 5056), + garden: new Position(1856, 5064), + formal_garden: new Position(1872, 5064), + parlor: new Position(1856, 5112), + kitchen: new Position(1872, 5112), + dining_room: new Position(1888, 5112), + bedroom: new Position(1904, 5112), + skill_hall: new Position(1864, 5104), + quest_hall: new Position(1912, 5104), portal_chamber: new Position(1864, 5088), - combat_room: new Position(1880, 5088), - games_room: new Position(1896, 5088), - treasure_room: new Position(1912, 5088), - chapel: new Position(1872, 5096), - study: new Position(1888, 5096), - throne_room: new Position(1904, 5096), - workshop: new Position(1856, 5096), - oubliette: new Position(1904, 5080), - costume_room: new Position(1904, 5064, 0) + combat_room: new Position(1880, 5088), + games_room: new Position(1896, 5088), + treasure_room: new Position(1912, 5088), + chapel: new Position(1872, 5096), + study: new Position(1888, 5096), + throne_room: new Position(1904, 5096), + workshop: new Position(1856, 5096), + oubliette: new Position(1904, 5080), + costume_room: new Position(1904, 5064, 0), }; - /** * A map of room builder widget button ids to their respective room types. */ @@ -88,10 +83,9 @@ export const roomBuilderButtonMap: { [key: number]: RoomType } = { 177: 'treasure_room', // @TODO dungeon corridor 178: 'treasure_room', // @TODO dungeon junction 179: 'treasure_room', // @TODO dungeon stair - 180: 'treasure_room' + 180: 'treasure_room', }; - export const instance1 = new Position(6400, 6400); export const instance1PohSpawn = new Position(6400 + 36, 6400 + 36); export const instance1Max = new Position(6400 + 64, 6400 + 64); diff --git a/src/plugins/skills/construction/home-saver.ts b/src/plugins/skills/construction/home-saver.ts index 37055fe0e..c0014cd94 100644 --- a/src/plugins/skills/construction/home-saver.ts +++ b/src/plugins/skills/construction/home-saver.ts @@ -1,20 +1,17 @@ -import type { Player } from '@engine/world/actor/player/player'; -import type { ConstructedRegion } from '@engine/world/map/region'; -import JSON5 from 'json5'; import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; -import { logger } from '@runejs/common'; import { join } from 'path'; +import type { Player } from '@engine/world/actor/player/player'; +import type { ConstructedRegion } from '@engine/world/map/region'; import type { Room } from '@plugins/skills/construction/house'; import { House } from '@plugins/skills/construction/house'; - +import { logger } from '@runejs/common'; +import JSON5 from 'json5'; /** * Gets the PoH save file name for the given player. * @param player */ -const getSaveFileName = (player: Player): string => - `${player.username.toLowerCase().replace(/ /g, '_')}.json5`; - +const getSaveFileName = (player: Player): string => `${player.username.toLowerCase().replace(/ /g, '_')}.json5`; /** * Loads and returns the given player's PoH as a ConstructedRegion object. @@ -24,7 +21,7 @@ const getSaveFileName = (player: Player): string => export const loadHouse = (player: Player): House | null => { const houseSaveDir = join('data', 'houses'); - if(!existsSync(houseSaveDir)) { + if (!existsSync(houseSaveDir)) { mkdirSync(houseSaveDir); return null; } @@ -33,12 +30,12 @@ export const loadHouse = (player: Player): House | null => { try { const customMapFile = readFileSync(filePath, 'utf-8'); - if(!customMapFile) { + if (!customMapFile) { return null; } const customMap = JSON5.parse(customMapFile); - if(!customMap) { + if (!customMap) { return null; } @@ -46,27 +43,26 @@ export const loadHouse = (player: Player): House | null => { const house = new House(); house.copyRooms(loadedHouse.rooms); return house; - } catch(error) { + } catch (error) { logger.error(`Error loading player house for ${player.username}.`); logger.error(error); return null; } }; - /** * Saves the given player's house as a JSON5 file. * @param player */ export const saveHouse = (player: Player): void => { const customMap = player.metadata.customMap as ConstructedRegion; - if(!customMap) { + if (!customMap) { return; } const houseSaveDir = join('data', 'houses'); - if(!existsSync(houseSaveDir)) { + if (!existsSync(houseSaveDir)) { mkdirSync(houseSaveDir); } @@ -77,7 +73,7 @@ export const saveHouse = (player: Player): void => { try { writeFileSync(filePath, JSON5.stringify(house, null, 4)); - } catch(error) { + } catch (error) { logger.error(`Error saving player house for ${player.username}.`); logger.error(error); } diff --git a/src/plugins/skills/construction/house.ts b/src/plugins/skills/construction/house.ts index 39ec69998..f7f61d400 100644 --- a/src/plugins/skills/construction/house.ts +++ b/src/plugins/skills/construction/house.ts @@ -1,57 +1,59 @@ -import type { RoomType -} from '@plugins/skills/construction/con-constants'; -import { - instance1, instance1Max, - instance1PohSpawn, instance2, instance2Max, - MAP_SIZE, roomTemplates -} from '@plugins/skills/construction/con-constants'; -import type { Position } from '@engine/world/position'; +import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; import type { ConstructedRegion } from '@engine/world/map/region'; import { ConstructedChunk } from '@engine/world/map/region'; -import type { Player } from '@engine/world/actor/player/player'; +import type { Position } from '@engine/world/position'; +import type { RoomType } from '@plugins/skills/construction/con-constants'; +import { + MAP_SIZE, + instance1, + instance1Max, + instance1PohSpawn, + instance2, + instance2Max, + roomTemplates, +} from '@plugins/skills/construction/con-constants'; import { loadHouse } from '@plugins/skills/construction/home-saver'; -import { activeWorld } from '@engine/world'; - export const openHouse = (player: Player): void => { let pohPosition: Position = instance1; let playerSpawn: Position = instance1PohSpawn; - if(player.position.within(instance1, instance1Max, false)) { + if (player.position.within(instance1, instance1Max, false)) { playerSpawn = player.position.copy().setY(player.position.y + 64); pohPosition = instance2; - } else if(player.position.within(instance2, instance2Max, false)) { + } else if (player.position.within(instance2, instance2Max, false)) { playerSpawn = player.position.copy().setY(player.position.y - 64); } const playerHouse = loadHouse(player); - if(playerHouse) { + if (playerHouse) { player.metadata.customMap = { renderPosition: pohPosition, - chunks: playerHouse.rooms + chunks: playerHouse.rooms, } as ConstructedRegion; } player.teleport(playerSpawn); - if(!player.metadata.customMap) { + if (!player.metadata.customMap) { const house = new House(); house.rooms[0][6][6] = new Room('garden'); player.metadata.customMap = { renderPosition: pohPosition, - chunks: house.rooms + chunks: house.rooms, } as ConstructedRegion; } else { player.metadata.customMap.renderPosition = pohPosition; } - for(let plane = 0; plane < 3; plane++) { - for(let chunkX = 0; chunkX < 13; chunkX++) { - for(let chunkY = 0; chunkY < 13; chunkY++) { + for (let plane = 0; plane < 3; plane++) { + for (let chunkX = 0; chunkX < 13; chunkX++) { + for (let chunkY = 0; chunkY < 13; chunkY++) { const room = player.metadata.customMap.chunks[plane][chunkX][chunkY]; - if(!room) { + if (!room) { continue; } @@ -66,20 +68,18 @@ export const openHouse = (player: Player): void => { player.sendMessage(`Welcome home.`); }; - export class House { - public rooms: (Room | null)[][][]; public constructor() { this.rooms = new Array(4); - for(let level = 0; level < 4; level++) { + for (let level = 0; level < 4; level++) { this.rooms[level] = new Array(MAP_SIZE); - for(let x = 0; x < MAP_SIZE; x++) { + for (let x = 0; x < MAP_SIZE; x++) { this.rooms[level][x] = new Array(MAP_SIZE).fill(null); - if(level === 0) { - for(let y = 0; y < MAP_SIZE; y++) { + if (level === 0) { + for (let y = 0; y < MAP_SIZE; y++) { this.rooms[level][x][y] = new Room('empty_grass'); } } @@ -88,9 +88,9 @@ export class House { } public copyRooms(rooms: (Room | null)[][][]): void { - for(let level = 0; level < 4; level++) { - for(let x = 0; x < MAP_SIZE; x++) { - for(let y = 0; y < MAP_SIZE; y++) { + for (let level = 0; level < 4; level++) { + for (let x = 0; x < MAP_SIZE; x++) { + for (let y = 0; y < MAP_SIZE; y++) { const existingRoom = rooms[level][x][y] ?? null; this.rooms[level][x][y] = existingRoom ? new Room(existingRoom.type, existingRoom.orientation) : null; @@ -98,12 +98,9 @@ export class House { } } } - } - export class Room extends ConstructedChunk { - public readonly type: RoomType; public constructor(type: RoomType, orientation: number = 0) { @@ -114,5 +111,4 @@ export class Room extends ConstructedChunk { public getTemplatePosition(): Position { return roomTemplates[this.type]; } - } diff --git a/src/plugins/skills/construction/index.ts b/src/plugins/skills/construction/index.ts index 054d1a4e8..c28e5b761 100644 --- a/src/plugins/skills/construction/index.ts +++ b/src/plugins/skills/construction/index.ts @@ -1,10 +1,9 @@ -import { instance1, instance1Max, instance2, instance2Max, roomBuilderButtonMap } from './con-constants'; -import { doorHotspotHandler, roomBuilderWidgetHandler } from '@plugins/skills/construction/room-builder'; -import { openHouse } from '@plugins/skills/construction/house'; -import { saveHouse } from '@plugins/skills/construction/home-saver'; import type { PlayerCommandAction } from '@engine/action/pipe/player-command.action'; import type { PlayerInitAction } from '@engine/action/pipe/player-init.action'; - +import { saveHouse } from '@plugins/skills/construction/home-saver'; +import { openHouse } from '@plugins/skills/construction/house'; +import { doorHotspotHandler, roomBuilderWidgetHandler } from '@plugins/skills/construction/room-builder'; +import { instance1, instance1Max, instance2, instance2Max, roomBuilderButtonMap } from './con-constants'; export default { pluginId: 'rs:construction', @@ -13,36 +12,35 @@ export default { type: 'button', widgetIds: 402, buttonIds: Object.keys(roomBuilderButtonMap).map(key => parseInt(key, 10)), - handler: roomBuilderWidgetHandler + handler: roomBuilderWidgetHandler, }, { type: 'object_interaction', - objectIds: [ 15313, 15314 ], + objectIds: [15313, 15314], options: 'build', walkTo: true, - handler: doorHotspotHandler + handler: doorHotspotHandler, }, { type: 'player_command', - commands: [ 'con', 'poh', 'house' ], - handler: ({ player }: PlayerCommandAction): void => openHouse(player) + commands: ['con', 'poh', 'house'], + handler: ({ player }: PlayerCommandAction): void => openHouse(player), }, { type: 'player_command', - commands: [ 'savepoh', 'savehouse' ], + commands: ['savepoh', 'savehouse'], handler: ({ player }: PlayerCommandAction): void => { player.sendMessage(`Saving house data...`); saveHouse(player); - } + }, }, { type: 'player_init', handler: ({ player }: PlayerInitAction): void => { - if(player.position.within(instance1, instance1Max, false) || - player.position.within(instance2, instance2Max, false)) { + if (player.position.within(instance1, instance1Max, false) || player.position.within(instance2, instance2Max, false)) { openHouse(player); } - } - } - ] + }, + }, + ], }; diff --git a/src/plugins/skills/construction/room-builder.ts b/src/plugins/skills/construction/room-builder.ts index 3167b50c3..2836c4544 100644 --- a/src/plugins/skills/construction/room-builder.ts +++ b/src/plugins/skills/construction/room-builder.ts @@ -1,20 +1,17 @@ -import type { - objectInteractionActionHandler -} from '@engine/action/pipe/object-interaction.action'; -import { openHouse, Room } from '@plugins/skills/construction/house'; -import { MAP_SIZE, roomBuilderButtonMap } from '@plugins/skills/construction/con-constants'; import type { buttonActionHandler } from '@engine/action/pipe/button.action'; -import { getCurrentRoom } from '@plugins/skills/construction/util'; +import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { dialogue, execute, goto } from '@engine/world/actor/dialogue'; import type { Player } from '@engine/world/actor/player/player'; import type { Coords } from '@engine/world/position'; -import { dialogue, execute, goto } from '@engine/world/actor/dialogue'; +import { MAP_SIZE, roomBuilderButtonMap } from '@plugins/skills/construction/con-constants'; +import { Room, openHouse } from '@plugins/skills/construction/house'; +import { getCurrentRoom } from '@plugins/skills/construction/util'; import { logger } from '@runejs/common'; - const newRoomOriention = (player: Player): number => { const currentRoom = getCurrentRoom(player); - if(!currentRoom) { + if (!currentRoom) { return 0; } @@ -26,19 +23,19 @@ const newRoomOriention = (player: Player): number => { let orientation = 0; - if(playerLocalX === 7) { + if (playerLocalX === 7) { // build east deltaX = 1; orientation = 1; - } else if(playerLocalX === 0) { + } else if (playerLocalX === 0) { // build west deltaX = -1; orientation = 3; - } else if(playerLocalY === 7) { + } else if (playerLocalY === 7) { // build north deltaY = 1; orientation = 0; - } else if(playerLocalY === 0) { + } else if (playerLocalY === 0) { // build south deltaY = -1; orientation = 2; @@ -47,11 +44,10 @@ const newRoomOriention = (player: Player): number => { return orientation; }; - export const canBuildNewRoom = (player: Player): Coords | null => { const currentRoom = getCurrentRoom(player); - if(!currentRoom) { + if (!currentRoom) { return null; } @@ -61,42 +57,42 @@ export const canBuildNewRoom = (player: Player): Coords | null => { let buildX = currentRoom.x; let buildY = currentRoom.y; - if(playerLocalX === 7) { + if (playerLocalX === 7) { // build east - if(currentRoom.x < MAP_SIZE - 3) { + if (currentRoom.x < MAP_SIZE - 3) { buildX = currentRoom.x + 1; } - } else if(playerLocalX === 0) { + } else if (playerLocalX === 0) { // build west - if(currentRoom.x > 2) { + if (currentRoom.x > 2) { buildX = currentRoom.x - 1; } - } else if(playerLocalY === 7) { + } else if (playerLocalY === 7) { // build north - if(currentRoom.y < MAP_SIZE - 3) { + if (currentRoom.y < MAP_SIZE - 3) { buildY = currentRoom.y + 1; } - } else if(playerLocalY === 0) { + } else if (playerLocalY === 0) { // build south - if(currentRoom.y > 2) { + if (currentRoom.y > 2) { buildY = currentRoom.y - 1; } } - if(buildX === currentRoom.x && buildY === currentRoom.y) { + if (buildX === currentRoom.x && buildY === currentRoom.y) { player.sendMessage(`You can not build there.`); return null; } const playerCustomMap = player.metadata.customMap; - if(!playerCustomMap) { + if (!playerCustomMap) { logger.error(`Player ${player.username} does not have a custom map.`); return null; } const rooms = playerCustomMap.chunks as Room[][][]; const existingRoom = rooms[player.position.level][buildX][buildY]; - if(existingRoom && existingRoom.type !== 'empty_grass' && existingRoom.type !== 'empty') { + if (existingRoom && existingRoom.type !== 'empty_grass' && existingRoom.type !== 'empty') { player.sendMessage(`${existingRoom.type} already exists there`); // @TODO return null; } @@ -104,24 +100,23 @@ export const canBuildNewRoom = (player: Player): Coords | null => { return { x: buildX, y: buildY, - level: player.position.level + level: player.position.level, }; }; - export const roomBuilderWidgetHandler: buttonActionHandler = async ({ player, buttonId }) => { const newRoomCoords = canBuildNewRoom(player); - if(!newRoomCoords) { + if (!newRoomCoords) { return; } const chosenRoomType = roomBuilderButtonMap[buttonId]; - if(!chosenRoomType) { + if (!chosenRoomType) { return; } const playerCustomMap = player.metadata.customMap; - if(!playerCustomMap) { + if (!playerCustomMap) { logger.error(`Player ${player.username} does not have a custom map.`); return; } @@ -133,32 +128,35 @@ export const roomBuilderWidgetHandler: buttonActionHandler = async ({ player, bu openHouse(player); - await dialogue([ player ], [ - (options, tag_Home) => [ - 'Rotate Counter-Clockwise', [ - execute(() => { - createdRoom.orientation = createdRoom.orientation > 0 ? createdRoom.orientation - 1 : 3; - openHouse(player); - }), - goto('tag_Home') + await dialogue( + [player], + [ + (options, tag_Home) => [ + 'Rotate Counter-Clockwise', + [ + execute(() => { + createdRoom.orientation = createdRoom.orientation > 0 ? createdRoom.orientation - 1 : 3; + openHouse(player); + }), + goto('tag_Home'), + ], + 'Rotate Clockwise', + [ + execute(() => { + createdRoom.orientation = createdRoom.orientation < 3 ? createdRoom.orientation + 1 : 0; + openHouse(player); + }), + goto('tag_Home'), + ], + 'Accept', + [execute(() => {})], ], - 'Rotate Clockwise', [ - execute(() => { - createdRoom.orientation = createdRoom.orientation < 3 ? createdRoom.orientation + 1 : 0; - openHouse(player); - }), - goto('tag_Home') - ], - 'Accept', [ - execute(() => {}) - ] - ] - ]); + ], + ); }; - export const doorHotspotHandler: objectInteractionActionHandler = ({ player }) => { - if(!canBuildNewRoom(player)) { + if (!canBuildNewRoom(player)) { return; } diff --git a/src/plugins/skills/construction/util.ts b/src/plugins/skills/construction/util.ts index 2309f460e..684f548a6 100644 --- a/src/plugins/skills/construction/util.ts +++ b/src/plugins/skills/construction/util.ts @@ -1,8 +1,7 @@ +import { activeWorld } from '@engine/world'; import type { Player } from '@engine/world/actor/player/player'; import type { Coords } from '@engine/world/position'; import { Position } from '@engine/world/position'; -import { activeWorld } from '@engine/world'; - /** * Finds the local coordinates of the room that the player is currently in within their PoH. @@ -12,7 +11,7 @@ import { activeWorld } from '@engine/world'; export const getCurrentRoom = (player: Player): Coords | null => { const customMap = player.metadata?.customMap; - if(!customMap) { + if (!customMap) { return null; } @@ -28,6 +27,6 @@ export const getCurrentRoom = (player: Player): Coords | null => { return { x: currentRoomX, y: currentRoomY, - level: player.position.level + level: player.position.level, }; }; diff --git a/src/plugins/skills/crafting/sheep-plugin.plugin.ts b/src/plugins/skills/crafting/sheep-plugin.plugin.ts index 85f1e5bc1..9c0444a7b 100644 --- a/src/plugins/skills/crafting/sheep-plugin.plugin.ts +++ b/src/plugins/skills/crafting/sheep-plugin.plugin.ts @@ -1,14 +1,12 @@ -import { itemIds } from '@engine/world/config/item-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { animationIds } from '@engine/world/config/animation-ids'; import type { itemOnNpcActionHandler } from '@engine/action/pipe/item-on-npc.action'; import type { npcInitActionHandler } from '@engine/action/pipe/npc-init.action'; - +import { animationIds } from '@engine/world/config/animation-ids'; +import { itemIds } from '@engine/world/config/item-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; const initAction: npcInitActionHandler = ({ npc }) => { // this used to use `setInterval` but will need rewriting to be synced with ticks // see https://github.com/runejs/server/issues/417 - // setInterval(() => { // if(Math.random() >= 0.66) { // npc.say(`Baa!`); @@ -52,14 +50,14 @@ export default { { type: 'npc_init', npcs: 'rs:sheep', - handler: initAction + handler: initAction, }, { type: 'item_on_npc', npcs: 'rs:sheep', - itemIds: [ itemIds.shears, itemIds.recruitmentDrive.shears ], + itemIds: [itemIds.shears, itemIds.recruitmentDrive.shears], walkTo: true, - handler: shearAction - } - ] + handler: shearAction, + }, + ], }; diff --git a/src/plugins/skills/crafting/spinning-wheel.plugin.ts b/src/plugins/skills/crafting/spinning-wheel.plugin.ts index ed4b15ea9..5b43f5388 100644 --- a/src/plugins/skills/crafting/spinning-wheel.plugin.ts +++ b/src/plugins/skills/crafting/spinning-wheel.plugin.ts @@ -1,14 +1,14 @@ -import { soundIds } from '@engine/world/config/sound-ids'; -import { itemIds } from '@engine/world/config/item-ids'; -import { Skill } from '@engine/world/actor/skills'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { objectIds } from '@engine/world/config/object-ids'; -import { findItem, widgets } from '@engine/config/config-handler'; -import { logger } from '@runejs/common'; import type { ButtonAction, buttonActionHandler } from '@engine/action/pipe/button.action'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem, widgets } from '@engine/config/config-handler'; import { ActorTask } from '@engine/task/impl/actor-task'; import type { Player } from '@engine/world/actor/player/player'; +import { Skill } from '@engine/world/actor/skills'; +import { animationIds } from '@engine/world/config/animation-ids'; +import { itemIds } from '@engine/world/config/item-ids'; +import { objectIds } from '@engine/world/config/object-ids'; +import { soundIds } from '@engine/world/config/sound-ids'; +import { logger } from '@runejs/common'; interface Spinnable { input: number | number[]; @@ -26,27 +26,22 @@ interface SpinnableButton { const ballOfWool: Spinnable = { input: itemIds.wool, output: itemIds.ballOfWool, experience: 2.5, requiredLevel: 1 }; const bowString: Spinnable = { input: itemIds.flax, output: itemIds.bowstring, experience: 15, requiredLevel: 10 }; const rootsCbowString: Spinnable = { - input: [ - itemIds.roots.oak, - itemIds.roots.willow, - itemIds.roots.maple, - itemIds.roots.yew - ], + input: [itemIds.roots.oak, itemIds.roots.willow, itemIds.roots.maple, itemIds.roots.yew], output: itemIds.crossbowString, experience: 15, - requiredLevel: 10 + requiredLevel: 10, }; const sinewCbowString: Spinnable = { input: itemIds.sinew, output: itemIds.crossbowString, experience: 15, - requiredLevel: 10 + requiredLevel: 10, }; const magicAmuletString: Spinnable = { input: itemIds.roots.magic, output: itemIds.magicString, experience: 30, - requiredLevel: 19 + requiredLevel: 19, }; const widgetButtonIds: Map = new Map([ [100, { shouldTakeInput: false, count: 1, spinnable: ballOfWool }], @@ -71,9 +66,9 @@ const widgetButtonIds: Map = new Map { +export const openSpinningInterface: objectInteractionActionHandler = details => { details.player.interfaceState.openWidget(widgets.whatWouldYouLikeToSpin, { - slot: 'screen' + slot: 'screen', }); }; @@ -111,11 +106,7 @@ class SpinProductTask extends ActorTask { */ private currentItemIndex = 0; - constructor( - player: Player, - spinnable: Spinnable, - count: number, - ) { + constructor(player: Player, spinnable: Spinnable, count: number) { super(player); this.spinnable = spinnable; this.count = count; @@ -140,9 +131,9 @@ class SpinProductTask extends ActorTask { if (!this.actor.hasItemInInventory(this.currentItem)) { let cancel = false; if (isArray) { - if (this.currentItemIndex < ( this.spinnable.input).length) { + if (this.currentItemIndex < (this.spinnable.input).length) { this.currentItemIndex++; - this.currentItem = ( this.spinnable.input)[this.currentItemIndex]; + this.currentItem = (this.spinnable.input)[this.currentItemIndex]; } else { cancel = true; } @@ -179,7 +170,7 @@ const spinProduct: any = (details: ButtonAction, spinnable: Spinnable, count: nu details.player.enqueueTask(SpinProductTask, [spinnable, count]); }; -export const buttonClicked: buttonActionHandler = (details) => { +export const buttonClicked: buttonActionHandler = details => { // Check if player might be spawning widget clientside if (!details.player.interfaceState.findWidget(459)) { return; @@ -197,7 +188,10 @@ export const buttonClicked: buttonActionHandler = (details) => { if (!details.player.skills.hasLevel(Skill.CRAFTING, product.spinnable.requiredLevel)) { const outputName = findItem(product.spinnable.output)?.name || ''; - details.player.sendMessage(`You need a crafting level of ${product.spinnable.requiredLevel} to craft ${outputName.toLowerCase()}.`, true); + details.player.sendMessage( + `You need a crafting level of ${product.spinnable.requiredLevel} to craft ${outputName.toLowerCase()}.`, + true, + ); return; } @@ -206,7 +200,7 @@ export const buttonClicked: buttonActionHandler = (details) => { spinProduct(details, product.spinnable, product.count); } else { // We should prepare for a number to be sent from the client - const numericInputSpinSub = details.player.numericInputEvent.subscribe((number) => { + const numericInputSpinSub = details.player.numericInputEvent.subscribe(number => { actionCancelledSpinSub?.unsubscribe(); numericInputSpinSub?.unsubscribe(); // When a number is recieved we can start crafting the product @@ -221,8 +215,6 @@ export const buttonClicked: buttonActionHandler = (details) => { // Ask the player to enter how many they want to create details.player.outgoingPackets.showNumberInputDialogue(); } - - }; export default { @@ -231,15 +223,15 @@ export default { { type: 'object_interaction', objectIds: objectIds.spinningWheel, - options: [ 'spin' ], + options: ['spin'], walkTo: true, - handler: openSpinningInterface + handler: openSpinningInterface, }, { type: 'button', widgetId: widgets.whatWouldYouLikeToSpin, buttonIds: Array.from(widgetButtonIds.keys()), - handler: buttonClicked - } - ] + handler: buttonClicked, + }, + ], }; diff --git a/src/plugins/skills/firemaking/chance.ts b/src/plugins/skills/firemaking/chance.ts index b8833d487..7e8ce6a8c 100644 --- a/src/plugins/skills/firemaking/chance.ts +++ b/src/plugins/skills/firemaking/chance.ts @@ -14,7 +14,7 @@ export const canLight = (logLevel: number, playerLevel: number): boolean => { playerLevel++; const hostRatio = Math.random() * logLevel; - const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); + const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + logLevel * 0.01)); return hostRatio < clientRatio; }; @@ -35,6 +35,6 @@ export const canChain = (logLevel: number, playerLevel: number): boolean => { playerLevel++; const hostRatio = Math.random() * logLevel; - const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); + const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + logLevel * 0.01)); return clientRatio - hostRatio < 3.5; }; diff --git a/src/plugins/skills/firemaking/data.ts b/src/plugins/skills/firemaking/data.ts index fdfeecb32..b0a9b3d11 100644 --- a/src/plugins/skills/firemaking/data.ts +++ b/src/plugins/skills/firemaking/data.ts @@ -4,51 +4,43 @@ import type { Burnable } from './types'; // using ! here because we know the items exist export const FIREMAKING_LOGS: Burnable[] = [ { - logItem: findItem('rs:logs')!, requiredLevel: 1, - experienceGained: 40 + experienceGained: 40, }, { - logItem: findItem('rs:oak_logs')!, requiredLevel: 15, - experienceGained: 60 + experienceGained: 60, }, { - logItem: findItem('rs:willow_logs')!, requiredLevel: 30, - experienceGained: 90 + experienceGained: 90, }, { - logItem: findItem('rs:teak_logs')!, requiredLevel: 35, - experienceGained: 105 + experienceGained: 105, }, { - logItem: findItem('rs:maple_logs')!, requiredLevel: 45, - experienceGained: 135 + experienceGained: 135, }, { - logItem: findItem('rs:mahogany_logs')!, requiredLevel: 50, - experienceGained: 157.5 + experienceGained: 157.5, }, { - logItem: findItem('rs:yew_logs')!, requiredLevel: 60, - experienceGained: 202.5 + experienceGained: 202.5, }, { - logItem: findItem('rs:magic_logs')!, requiredLevel: 75, - experienceGained: 303.8 - } + experienceGained: 303.8, + }, ]; diff --git a/src/plugins/skills/firemaking/firemaking-task.ts b/src/plugins/skills/firemaking/firemaking-task.ts index a6f4bddbd..ac637fbda 100644 --- a/src/plugins/skills/firemaking/firemaking-task.ts +++ b/src/plugins/skills/firemaking/firemaking-task.ts @@ -42,10 +42,7 @@ class FiremakingTask extends ActorWorldItemInteractionTask { * @param player The player that is attempting to light the fire. * @param logWorldItem The world item that represents the log. */ - constructor( - player: Player, - logWorldItem: WorldItem - ) { + constructor(player: Player, logWorldItem: WorldItem) { super(player, logWorldItem); const logInfo = FIREMAKING_LOGS.find(l => l.logItem.gameId === logWorldItem.itemId); @@ -126,5 +123,5 @@ class FiremakingTask extends ActorWorldItemInteractionTask { * @param worldItemLog The WorldItem that represents the log. */ export function runFiremakingTask(player: Player, worldItemLog: WorldItem) { - player.enqueueTask(FiremakingTask, [ worldItemLog ]); + player.enqueueTask(FiremakingTask, [worldItemLog]); } diff --git a/src/plugins/skills/firemaking/index.ts b/src/plugins/skills/firemaking/index.ts index 15c5f9b4e..4f9cda7d2 100644 --- a/src/plugins/skills/firemaking/index.ts +++ b/src/plugins/skills/firemaking/index.ts @@ -1,15 +1,15 @@ -import { FIREMAKING_LOGS } from './data'; -import { canChain } from './chance'; -import { canLightFireAtCurrentPosition, lightFire } from './light-fire'; -import { runFiremakingTask } from './firemaking-task'; -import type { itemOnItemActionHandler, ItemOnItemActionHook } from '@engine/action/pipe/item-on-item.action'; +import type { ItemOnItemActionHook, itemOnItemActionHandler } from '@engine/action/pipe/item-on-item.action'; import type { ItemOnWorldItemActionHook } from '@engine/action/pipe/item-on-world-item.action'; import { itemIds } from '@engine/world/config/item-ids'; +import { canChain } from './chance'; +import { FIREMAKING_LOGS } from './data'; +import { runFiremakingTask } from './firemaking-task'; +import { canLightFireAtCurrentPosition, lightFire } from './light-fire'; /** * Action hook for lighting a log with a tinderbox in the player's inventory. */ -const tinderboxOnLogHandler: itemOnItemActionHandler = (details) => { +const tinderboxOnLogHandler: itemOnItemActionHandler = details => { const { player, usedItem, usedWithItem, usedSlot, usedWithSlot } = details; if (player.metadata.lastFire && Date.now() - player.metadata.lastFire < 600) { @@ -39,8 +39,11 @@ const tinderboxOnLogHandler: itemOnItemActionHandler = (details) => { const worldItemLog = player.instance.spawnWorldItem(log, player.position, { owner: player, expires: 300 }); // TODO (jameskmonger) chaining functionality needs documentation, I can't find anything about it online - if (player.metadata.lastFire && Date.now() - player.metadata.lastFire < 1200 && - canChain(skillInfo.requiredLevel, player.skills.firemaking.level)) { + if ( + player.metadata.lastFire && + Date.now() - player.metadata.lastFire < 1200 && + canChain(skillInfo.requiredLevel, player.skills.firemaking.level) + ) { lightFire(player, player.position, worldItemLog, skillInfo.experienceGained); } else { player.sendMessage('You attempt to light the logs.'); @@ -61,14 +64,14 @@ export default { { type: 'item_on_item', items: FIREMAKING_LOGS.map(log => ({ item1: itemIds.tinderbox, item2: log.logItem.gameId })), - handler: tinderboxOnLogHandler + handler: tinderboxOnLogHandler, } as ItemOnItemActionHook, { type: 'item_on_world_item', items: FIREMAKING_LOGS.map(log => ({ item: itemIds.tinderbox, worldItem: log.logItem.gameId })), handler: ({ player, usedWithItem }) => { runFiremakingTask(player, usedWithItem); - } - } as ItemOnWorldItemActionHook - ] + }, + } as ItemOnWorldItemActionHook, + ], }; diff --git a/src/plugins/skills/firemaking/light-fire.ts b/src/plugins/skills/firemaking/light-fire.ts index dc9d09414..0911cad49 100644 --- a/src/plugins/skills/firemaking/light-fire.ts +++ b/src/plugins/skills/firemaking/light-fire.ts @@ -23,15 +23,14 @@ const fireDurationTicks = (): number => { * @author jameskmonger */ export const canLightFireAtCurrentPosition = (player: Player): boolean => { - const existingFire = player.instance.getTileModifications(player.position).mods.spawnedObjects.find(o => ( - o.x === player.position.x - && o.y === player.position.y - && o.level === player.position.level - && o.type === 10 - )) + const existingFire = player.instance + .getTileModifications(player.position) + .mods.spawnedObjects.find( + o => o.x === player.position.x && o.y === player.position.y && o.level === player.position.level && o.type === 10, + ); return existingFire === undefined; -} +}; /** * Light a fire at the specified position. @@ -54,16 +53,16 @@ export const lightFire = (player: Player, position: Position, worldItemLog: Worl y: position.y, level: position.level, type: 10, - orientation: 0 + orientation: 0, }; player.playAnimation(null); player.sendMessage('The fire catches and the logs begin to burn.'); player.skills.firemaking.addExp(burnExp); - if(!player.walkingQueue.moveIfAble(-1, 0)) { - if(!player.walkingQueue.moveIfAble(1, 0)) { - if(!player.walkingQueue.moveIfAble(0, -1)) { + if (!player.walkingQueue.moveIfAble(-1, 0)) { + if (!player.walkingQueue.moveIfAble(1, 0)) { + if (!player.walkingQueue.moveIfAble(0, -1)) { player.walkingQueue.moveIfAble(0, 1); } } diff --git a/src/plugins/skills/firemaking/types.ts b/src/plugins/skills/firemaking/types.ts index 216710679..fec94c5fb 100644 --- a/src/plugins/skills/firemaking/types.ts +++ b/src/plugins/skills/firemaking/types.ts @@ -18,4 +18,4 @@ export type Burnable = { * The experience gained for lighting the log. */ experienceGained: number; -} +}; diff --git a/src/plugins/skills/fletching/fletching-constants.ts b/src/plugins/skills/fletching/fletching-constants.ts index 4e2b4380e..414301dc3 100644 --- a/src/plugins/skills/fletching/fletching-constants.ts +++ b/src/plugins/skills/fletching/fletching-constants.ts @@ -1,233 +1,290 @@ import { itemIds } from '@engine/world/config/item-ids'; import type { Fletchable } from '@plugins/skills/fletching/fletching-types'; - export const knifeId: number = itemIds.knife; -export const fletchables : Map> = new Map>([ - ['bow(u)', new Map([ - ['wood short', { - level: 1, - experience: 5, - item: { itemId: itemIds.bowunstrung.woodshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['wood long', { - level: 10, - experience: 10, - item: { itemId: itemIds.bowunstrung.woodlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['oak short', { - level: 20, - experience: 16.5, - item: { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['oak long', { - level: 25, - experience: 25, - item: { itemId: itemIds.bowunstrung.oaklong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['comp ogre', { - level: 30, - experience: 45, - item: { itemId: itemIds.bowunstrung.compogre, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['willow short', { - level: 35, - experience: 33.3, - item: { itemId: itemIds.bowunstrung.willowshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['willow long', { - level: 40, - experience: 41.5, - item: { itemId: itemIds.bowunstrung.willowlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['maple short', { - level: 50, - experience: 50, - item: { itemId: itemIds.bowunstrung.mapleshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['maple long', { - level: 55, - experience: 58.3, - item: { itemId: itemIds.bowunstrung.maplelong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['yew short', { - level: 65, - experience: 67.5, - item: { itemId: itemIds.bowunstrung.yewshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['yew long', { - level: 70, - experience: 75, - item: { itemId: itemIds.bowunstrung.yewlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['magic short', { - level: 80, - experience: 83.3, - item: { itemId: itemIds.bowunstrung.magicshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ['magic long', { - level: 85, - experience: 91.5, - item: { itemId: itemIds.bowunstrung.magiclong, amount: 1 }, - ingredient: [ - { itemId: itemIds.logs.normal, amount: 1 } - ] - }], - ])], - ['bow', new Map([ - ['wood short', { - level: 1, - experience: 5, - item: { itemId: itemIds.bowstrung.woodshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.woodshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['wood long', { - level: 10, - experience: 10, - item: { itemId: itemIds.bowstrung.woodlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.woodlong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['oak short', { - level: 20, - experience: 16.5, - item: { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['oak long', { - level: 25, - experience: 25, - item: { itemId: itemIds.bowstrung.oaklong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.oaklong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['comp ogre', { - level: 30, - experience: 45, - item: { itemId: itemIds.bowstrung.compogre, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.compogre, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['willow short', { - level: 35, - experience: 33.3, - item: { itemId: itemIds.bowstrung.willowshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.willowshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['willow long', { - level: 40, - experience: 41.5, - item: { itemId: itemIds.bowstrung.willowlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.willowlong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['maple short', { - level: 50, - experience: 50, - item: { itemId: itemIds.bowstrung.mapleshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.mapleshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['maple long', { - level: 55, - experience: 58.3, - item: { itemId: itemIds.bowstrung.maplelong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.maplelong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['yew short', { - level: 65, - experience: 67.5, - item: { itemId: itemIds.bowstrung.yewshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.yewshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['yew long', { - level: 70, - experience: 75, - item: { itemId: itemIds.bowstrung.yewlong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.yewlong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['magic short', { - level: 80, - experience: 83.3, - item: { itemId: itemIds.bowstrung.magicshort, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.magicshort, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ['magic long', { - level: 85, - experience: 91.5, - item: { itemId: itemIds.bowstrung.magiclong, amount: 1 }, - ingredient: [ - { itemId: itemIds.bowunstrung.magiclong, amount: 1 }, - { itemId: itemIds.bowstring, amount: 1 } - ] - }], - ])] -]) +export const fletchables: Map> = new Map>([ + [ + 'bow(u)', + new Map([ + [ + 'wood short', + { + level: 1, + experience: 5, + item: { itemId: itemIds.bowunstrung.woodshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'wood long', + { + level: 10, + experience: 10, + item: { itemId: itemIds.bowunstrung.woodlong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'oak short', + { + level: 20, + experience: 16.5, + item: { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'oak long', + { + level: 25, + experience: 25, + item: { itemId: itemIds.bowunstrung.oaklong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'comp ogre', + { + level: 30, + experience: 45, + item: { itemId: itemIds.bowunstrung.compogre, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'willow short', + { + level: 35, + experience: 33.3, + item: { itemId: itemIds.bowunstrung.willowshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'willow long', + { + level: 40, + experience: 41.5, + item: { itemId: itemIds.bowunstrung.willowlong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'maple short', + { + level: 50, + experience: 50, + item: { itemId: itemIds.bowunstrung.mapleshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'maple long', + { + level: 55, + experience: 58.3, + item: { itemId: itemIds.bowunstrung.maplelong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'yew short', + { + level: 65, + experience: 67.5, + item: { itemId: itemIds.bowunstrung.yewshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'yew long', + { + level: 70, + experience: 75, + item: { itemId: itemIds.bowunstrung.yewlong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'magic short', + { + level: 80, + experience: 83.3, + item: { itemId: itemIds.bowunstrung.magicshort, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + [ + 'magic long', + { + level: 85, + experience: 91.5, + item: { itemId: itemIds.bowunstrung.magiclong, amount: 1 }, + ingredient: [{ itemId: itemIds.logs.normal, amount: 1 }], + }, + ], + ]), + ], + [ + 'bow', + new Map([ + [ + 'wood short', + { + level: 1, + experience: 5, + item: { itemId: itemIds.bowstrung.woodshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.woodshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'wood long', + { + level: 10, + experience: 10, + item: { itemId: itemIds.bowstrung.woodlong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.woodlong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'oak short', + { + level: 20, + experience: 16.5, + item: { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.oakshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'oak long', + { + level: 25, + experience: 25, + item: { itemId: itemIds.bowstrung.oaklong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.oaklong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'comp ogre', + { + level: 30, + experience: 45, + item: { itemId: itemIds.bowstrung.compogre, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.compogre, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'willow short', + { + level: 35, + experience: 33.3, + item: { itemId: itemIds.bowstrung.willowshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.willowshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'willow long', + { + level: 40, + experience: 41.5, + item: { itemId: itemIds.bowstrung.willowlong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.willowlong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'maple short', + { + level: 50, + experience: 50, + item: { itemId: itemIds.bowstrung.mapleshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.mapleshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'maple long', + { + level: 55, + experience: 58.3, + item: { itemId: itemIds.bowstrung.maplelong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.maplelong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'yew short', + { + level: 65, + experience: 67.5, + item: { itemId: itemIds.bowstrung.yewshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.yewshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'yew long', + { + level: 70, + experience: 75, + item: { itemId: itemIds.bowstrung.yewlong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.yewlong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'magic short', + { + level: 80, + experience: 83.3, + item: { itemId: itemIds.bowstrung.magicshort, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.magicshort, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + [ + 'magic long', + { + level: 85, + experience: 91.5, + item: { itemId: itemIds.bowstrung.magiclong, amount: 1 }, + ingredient: [ + { itemId: itemIds.bowunstrung.magiclong, amount: 1 }, + { itemId: itemIds.bowstring, amount: 1 }, + ], + }, + ], + ]), + ], +]); diff --git a/src/plugins/skills/fletching/fletching-types.ts b/src/plugins/skills/fletching/fletching-types.ts index 7d7ac2456..80593a48a 100644 --- a/src/plugins/skills/fletching/fletching-types.ts +++ b/src/plugins/skills/fletching/fletching-types.ts @@ -1,4 +1,4 @@ -import type { Item }from '@engine/world/items/item'; +import type { Item } from '@engine/world/items/item'; export interface Fletchable { item: Item; level: number; diff --git a/src/plugins/skills/fletching/fletching.plugin.ts b/src/plugins/skills/fletching/fletching.plugin.ts index 8f798967d..8f6f49a16 100644 --- a/src/plugins/skills/fletching/fletching.plugin.ts +++ b/src/plugins/skills/fletching/fletching.plugin.ts @@ -1,7 +1,5 @@ - //fletching stuff goes below this! lets do it! export default { pluginId: 'rs:fletching', - }; diff --git a/src/plugins/skills/level-up-dialogue.plugin.ts b/src/plugins/skills/level-up-dialogue.plugin.ts index 73a4de77c..31c5fca00 100644 --- a/src/plugins/skills/level-up-dialogue.plugin.ts +++ b/src/plugins/skills/level-up-dialogue.plugin.ts @@ -1,24 +1,13 @@ import type { widgetInteractionActionHandler } from '@engine/action/pipe/widget-interaction.action'; -const widgetIds = [ - 158, 161, 175, - 167, 171, 170, - 168, 159, 177, - 165, 164, 163, - 160, 174, 169, - 166, 157, 176, - 173, 162, 172, -]; +const widgetIds = [158, 161, 175, 167, 171, 170, 168, 159, 177, 165, 164, 163, 160, 174, 169, 166, 157, 176, 173, 162, 172]; /** * Handles a level-up dialogue action. */ export const handler: widgetInteractionActionHandler = ({ player }) => player.interfaceState.closeChatOverlayWidget(); - export default { pluginId: 'rs:close_level_up_message', - hooks: [ - { type: 'widget_interaction', widgetIds, handler, cancelActions: false } - ] + hooks: [{ type: 'widget_interaction', widgetIds, handler, cancelActions: false }], }; diff --git a/src/plugins/skills/mining/chance.ts b/src/plugins/skills/mining/chance.ts index 1edeb1cc8..de170add9 100644 --- a/src/plugins/skills/mining/chance.ts +++ b/src/plugins/skills/mining/chance.ts @@ -10,14 +10,9 @@ import type { IHarvestable } from '@engine/world/config/harvestable-object'; * * @returns True if the tree was successfully cut, false otherwise */ -export const canMine = ( - ore: IHarvestable, - toolLevel: number, - miningLevel: number -): boolean => { +export const canMine = (ore: IHarvestable, toolLevel: number, miningLevel: number): boolean => { const successChance = randomBetween(0, 255); - const percentNeeded = - ore.baseChance + toolLevel + miningLevel; + const percentNeeded = ore.baseChance + toolLevel + miningLevel; return successChance <= percentNeeded; }; diff --git a/src/plugins/skills/mining/mining-task.ts b/src/plugins/skills/mining/mining-task.ts index 77b2d6c98..c6b0b7cf8 100644 --- a/src/plugins/skills/mining/mining-task.ts +++ b/src/plugins/skills/mining/mining-task.ts @@ -1,7 +1,3 @@ -import type { LandscapeObject } from '@runejs/filestore'; -import { checkForGemBoost } from '@engine/world/skill-util/glory-boost'; -import { rollGemType } from '@engine/world/skill-util/harvest-roll'; -import { canMine } from './chance'; import { findItem } from '@engine/config/config-handler'; import { equipmentIndices } from '@engine/config/item-config'; import { ActorLandscapeObjectInteractionTask } from '@engine/task/impl/actor-landscape-object-interaction-task'; @@ -14,6 +10,10 @@ import type { HarvestTool } from '@engine/world/config/harvest-tool'; import type { IHarvestable } from '@engine/world/config/harvestable-object'; import { selectWeightedItem } from '@engine/world/config/harvestable-object'; import { soundIds } from '@engine/world/config/sound-ids'; +import { checkForGemBoost } from '@engine/world/skill-util/glory-boost'; +import { rollGemType } from '@engine/world/skill-util/harvest-roll'; +import type { LandscapeObject } from '@runejs/filestore'; +import { canMine } from './chance'; /** * A task that handles mining. It is a subclass of ActorLandscapeObjectInteractionTask, which means that it will @@ -37,8 +37,12 @@ export class MiningTask extends ActorLandscapeObjectInteractionTask { */ private targetItemName: string; - - constructor(player: Player, landscapeObject: LandscapeObject, private readonly ore: IHarvestable, private readonly tool: HarvestTool) { + constructor( + player: Player, + landscapeObject: LandscapeObject, + private readonly ore: IHarvestable, + private readonly tool: HarvestTool, + ) { super(player, landscapeObject); const itemConfigId = typeof ore.items === 'string' ? ore.items : selectWeightedItem(ore.items); @@ -48,7 +52,7 @@ export class MiningTask extends ActorLandscapeObjectInteractionTask { throw new Error(`Could not find item with ID ${itemConfigId}`); } - this.targetItemName = item.name.toLowerCase().replace(' ore', '') + this.targetItemName = item.name.toLowerCase().replace(' ore', ''); } private isGemRock(): boolean { @@ -104,17 +108,13 @@ export class MiningTask extends ActorLandscapeObjectInteractionTask { // Get tool level, and set it to 2 if the tool is an iron hatchet or iron pickaxe // TODO why is this set to 2? Was ported from the old code let toolLevel = this.tool.level - 1; - if(this.tool.itemId === 1349 || this.tool.itemId === 1267) { + if (this.tool.itemId === 1349 || this.tool.itemId === 1267) { toolLevel = 2; } // roll for success - const succeeds = canMine( - { ...this.ore, baseChance: this.getGemMiningChance() }, - toolLevel, - this.actor.skills.mining.level - ); - if(!succeeds) { + const succeeds = canMine({ ...this.ore, baseChance: this.getGemMiningChance() }, toolLevel, this.actor.skills.mining.level); + if (!succeeds) { return; } @@ -124,9 +124,7 @@ export class MiningTask extends ActorLandscapeObjectInteractionTask { this.actor.giveItem(rollGemType()); } else { this.actor.sendMessage(`You manage to mine some ${this.targetItemName}.`); - const itemToGive = typeof this.ore.items === 'string' ? - this.ore.items : - selectWeightedItem(this.ore.items); + const itemToGive = typeof this.ore.items === 'string' ? this.ore.items : selectWeightedItem(this.ore.items); this.actor.giveItem(itemToGive); // TODO (Jameskmonger) handle Gem rocks and Pure essence rocks // if (itemToAdd === 1436 && details.player.skills.hasLevel(Skill.MINING, 30)) { @@ -171,8 +169,7 @@ export class MiningTask extends ActorLandscapeObjectInteractionTask { } // Base chance scaling from 28 to 70 based on level - let chance = this.ore.baseChance + - (this.actor.skills.mining.level - this.ore.level) * (70 - 28) / (99 - 40); + let chance = this.ore.baseChance + ((this.actor.skills.mining.level - this.ore.level) * (70 - 28)) / (99 - 40); // Glory multiplies chance by 3 (from 28-70 to 84-210) if (this.hasChargedGlory()) { diff --git a/src/plugins/skills/mining/mining.plugin.ts b/src/plugins/skills/mining/mining.plugin.ts index 2f48319bd..a9e3bf6bc 100644 --- a/src/plugins/skills/mining/mining.plugin.ts +++ b/src/plugins/skills/mining/mining.plugin.ts @@ -1,11 +1,11 @@ -import { Skill } from '@engine/world/actor/skills'; -import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; -import { MiningTask } from './mining-task'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { Skill } from '@engine/world/actor/skills'; import { getBestPickaxe } from '@engine/world/config/harvest-tool'; +import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; import { soundIds } from '@engine/world/config/sound-ids'; +import { MiningTask } from './mining-task'; -const action: objectInteractionActionHandler = (details) => { +const action: objectInteractionActionHandler = details => { // Get the mining details for the target rock const ore = getOreFromRock(details.object.objectId); @@ -27,7 +27,7 @@ const action: objectInteractionActionHandler = (details) => { return; } - if(!tool) { + if (!tool) { return; } @@ -39,14 +39,15 @@ const action: objectInteractionActionHandler = (details) => { details.player.enqueueTask(MiningTask, [details.object, ore, tool]); }; - export default { pluginId: 'rs:mining', - hooks: [ { - type: 'object_interaction', - options: [ 'mine' ], - objectIds: getAllOreIds(), - walkTo: true, - handler: action - } ] + hooks: [ + { + type: 'object_interaction', + options: ['mine'], + objectIds: getAllOreIds(), + walkTo: true, + handler: action, + }, + ], }; diff --git a/src/plugins/skills/mining/prospecting.plugin.ts b/src/plugins/skills/mining/prospecting.plugin.ts index 764a87d41..bf0da95b3 100644 --- a/src/plugins/skills/mining/prospecting.plugin.ts +++ b/src/plugins/skills/mining/prospecting.plugin.ts @@ -1,9 +1,9 @@ -import { soundIds } from '@engine/world/config/sound-ids'; -import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; -import { findItem } from '@engine/config/config-handler'; import type { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem } from '@engine/config/config-handler'; +import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; +import { soundIds } from '@engine/world/config/sound-ids'; -const action: objectInteractionActionHandler = (details) => { +const action: objectInteractionActionHandler = details => { details.player.sendMessage('You examine the rock for ores.'); details.player.face(details.position); const ore = getOreFromRock(details.object.objectId); @@ -33,11 +33,13 @@ const action: objectInteractionActionHandler = (details) => { export default { pluginId: 'rs:prospecting', - hooks: [ { - type: 'object_interaction', - options: [ 'prospect' ], - objectIds: getAllOreIds(), - walkTo: true, - handler: action - } ] + hooks: [ + { + type: 'object_interaction', + options: ['prospect'], + objectIds: getAllOreIds(), + walkTo: true, + handler: action, + }, + ], }; diff --git a/src/plugins/skills/prayer/bury-bones.plugin.ts b/src/plugins/skills/prayer/bury-bones.plugin.ts index 769c6bc3f..bc0c2bfd4 100644 --- a/src/plugins/skills/prayer/bury-bones.plugin.ts +++ b/src/plugins/skills/prayer/bury-bones.plugin.ts @@ -1,11 +1,11 @@ import type { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import { findItem, widgets } from '@engine/config/config-handler'; -import { giveAchievement, Achievements } from '@engine/world/actor/player/achievements'; +import { Achievements, giveAchievement } from '@engine/world/actor/player/achievements'; import { Skill } from '@engine/world/actor/skills'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; -const action: itemInteractionActionHandler = (details) => { +const action: itemInteractionActionHandler = details => { const { player, option } = details; if (option !== 'bury') return; @@ -62,7 +62,7 @@ export default { options: 'bury', itemIds: allBones, handler: action, - cancelOtherActions: true - } - ] + cancelOtherActions: true, + }, + ], }; diff --git a/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts index 48ecbc1da..fde0b9a55 100644 --- a/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts @@ -1,22 +1,15 @@ +import type { ItemOnObjectAction, itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; +import type { ObjectInteractionAction, objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem } from '@engine/config/config-handler'; +import type { Player } from '@engine/world/actor/player/player'; +import { itemIds } from '@engine/world/config/item-ids'; +import type { Item } from '@engine/world/items/item'; /** * @Author NickNick */ -import { - altars, - getEntityByAttr, - getEntityIds, - runes, - talismans, -} from '@plugins/skills/runecrafting/runecrafting-constants'; +import { altars, getEntityByAttr, getEntityIds, runes, talismans } from '@plugins/skills/runecrafting/runecrafting-constants'; import type { RunecraftingAltar } from '@plugins/skills/runecrafting/runecrafting-types'; -import { itemIds } from '@engine/world/config/item-ids'; -import type { Player } from '@engine/world/actor/player/player'; -import type { Item } from '@engine/world/items/item'; -import { findItem } from '@engine/config/config-handler'; import { logger } from '@runejs/common'; -import type { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/action/pipe/item-on-object.action'; -import type { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action/pipe/object-interaction.action'; - const enterAltar: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { const { player, object, item } = details; @@ -34,10 +27,12 @@ const enterAltar: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { } if (item.itemId === itemIds.talismans.elemental) { - if (rune.talisman.id === itemIds.talismans.air - || rune.talisman.id === itemIds.talismans.water - || rune.talisman.id === itemIds.talismans.earth - || rune.talisman.id === itemIds.talismans.fire) { + if ( + rune.talisman.id === itemIds.talismans.air || + rune.talisman.id === itemIds.talismans.water || + rune.talisman.id === itemIds.talismans.earth || + rune.talisman.id === itemIds.talismans.fire + ) { finishEnterAltar(player, item, altar); return; } @@ -52,7 +47,6 @@ const enterAltar: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { // Correct talisman. if (item.itemId === rune.talisman.id) { finishEnterAltar(player, item, altar); - } }; @@ -69,7 +63,6 @@ function finishEnterAltar(player: Player, item: Item, altar: RunecraftingAltar): player.teleport(altar.entrance); } - const exitAltar: objectInteractionActionHandler = (details: ObjectInteractionAction) => { const { player, object } = details; const altar = getEntityByAttr(altars, 'portalId', object.objectId); @@ -82,7 +75,6 @@ const exitAltar: objectInteractionActionHandler = (details: ObjectInteractionAct player.teleport(altar.exit); }; - export default { pluginId: 'rs:runecrafting_altars', hooks: [ @@ -91,12 +83,13 @@ export default { itemIds: getEntityIds(talismans, 'id'), objectIds: getEntityIds(altars, 'entranceId'), walkTo: true, - handler: enterAltar - }, { + handler: enterAltar, + }, + { type: 'object_interaction', objectIds: getEntityIds(altars, 'portalId'), walkTo: true, - handler: exitAltar - } - ] + handler: exitAltar, + }, + ], }; diff --git a/src/plugins/skills/runecrafting/runecrafting-constants.ts b/src/plugins/skills/runecrafting/runecrafting-constants.ts index 2a3ffa6f7..938d98e33 100644 --- a/src/plugins/skills/runecrafting/runecrafting-constants.ts +++ b/src/plugins/skills/runecrafting/runecrafting-constants.ts @@ -17,87 +17,126 @@ */ import { itemIds } from '@engine/world/config/item-ids'; -import type { RunecraftingAltar, RunecraftingCombinationRune, RunecraftingRune, RunecraftingTalisman, RunecraftingTiara } from '@plugins/skills/runecrafting/runecrafting-types'; import { Position } from '@engine/world/position'; +import type { + RunecraftingAltar, + RunecraftingCombinationRune, + RunecraftingRune, + RunecraftingTalisman, + RunecraftingTiara, +} from '@plugins/skills/runecrafting/runecrafting-types'; export const tiaras: Map = new Map([ - ['air', { - id: itemIds.tiaras.air, - config: 1, - level: 1, - xp: 25.0, - recipe: { ingredients: [itemIds.talismans.air, itemIds.tiaras.blank] } - }], - ['mind', { - id: itemIds.tiaras.mind, - config: 2, - level: 1, - xp: 27.5, - recipe: { ingredients: [itemIds.talismans.mind, itemIds.tiaras.blank] } - }], - ['water', { - id: itemIds.tiaras.water, - config: 4, - level: 1, - xp: 30, - recipe: { ingredients: [itemIds.talismans.water, itemIds.tiaras.blank] } - }], - ['body', { - id: itemIds.tiaras.body, - config: 32, - level: 1, - xp: 37.5, - recipe: { ingredients: [itemIds.talismans.body, itemIds.tiaras.blank] } - }], - ['earth', { - id: itemIds.tiaras.earth, - config: 8, - level: 1, - xp: 32.5, - recipe: { ingredients: [itemIds.talismans.earth, itemIds.tiaras.blank] } - }], - ['fire', { - id: itemIds.tiaras.fire, - config: 16, - level: 1, - xp: 35, - recipe: { ingredients: [itemIds.talismans.fire, itemIds.tiaras.blank] } - }], - ['cosmic', { - id: itemIds.tiaras.cosmic, - config: 64, - level: 1, - xp: 40, - recipe: { ingredients: [itemIds.talismans.cosmic, itemIds.tiaras.blank] } - }], - ['nature', { - id: itemIds.tiaras.nature, - config: 256, - level: 1, - xp: 45, - recipe: { ingredients: [itemIds.talismans.nature, itemIds.tiaras.blank] } - }], - ['chaos', { - id: itemIds.tiaras.chaos, - config: 128, - level: 1, - xp: 42.5, - recipe: { ingredients: [itemIds.talismans.chaos, itemIds.tiaras.blank] } - }], - ['law', { - id: itemIds.tiaras.law, - config: 512, - level: 1, - xp: 47.5, - recipe: { ingredients: [itemIds.talismans.law, itemIds.tiaras.blank] } - }], - ['death', { - id: itemIds.tiaras.death, - config: 1024, - level: 1, - xp: 50, - recipe: { ingredients: [itemIds.talismans.death, itemIds.tiaras.blank] } - }], + [ + 'air', + { + id: itemIds.tiaras.air, + config: 1, + level: 1, + xp: 25.0, + recipe: { ingredients: [itemIds.talismans.air, itemIds.tiaras.blank] }, + }, + ], + [ + 'mind', + { + id: itemIds.tiaras.mind, + config: 2, + level: 1, + xp: 27.5, + recipe: { ingredients: [itemIds.talismans.mind, itemIds.tiaras.blank] }, + }, + ], + [ + 'water', + { + id: itemIds.tiaras.water, + config: 4, + level: 1, + xp: 30, + recipe: { ingredients: [itemIds.talismans.water, itemIds.tiaras.blank] }, + }, + ], + [ + 'body', + { + id: itemIds.tiaras.body, + config: 32, + level: 1, + xp: 37.5, + recipe: { ingredients: [itemIds.talismans.body, itemIds.tiaras.blank] }, + }, + ], + [ + 'earth', + { + id: itemIds.tiaras.earth, + config: 8, + level: 1, + xp: 32.5, + recipe: { ingredients: [itemIds.talismans.earth, itemIds.tiaras.blank] }, + }, + ], + [ + 'fire', + { + id: itemIds.tiaras.fire, + config: 16, + level: 1, + xp: 35, + recipe: { ingredients: [itemIds.talismans.fire, itemIds.tiaras.blank] }, + }, + ], + [ + 'cosmic', + { + id: itemIds.tiaras.cosmic, + config: 64, + level: 1, + xp: 40, + recipe: { ingredients: [itemIds.talismans.cosmic, itemIds.tiaras.blank] }, + }, + ], + [ + 'nature', + { + id: itemIds.tiaras.nature, + config: 256, + level: 1, + xp: 45, + recipe: { ingredients: [itemIds.talismans.nature, itemIds.tiaras.blank] }, + }, + ], + [ + 'chaos', + { + id: itemIds.tiaras.chaos, + config: 128, + level: 1, + xp: 42.5, + recipe: { ingredients: [itemIds.talismans.chaos, itemIds.tiaras.blank] }, + }, + ], + [ + 'law', + { + id: itemIds.tiaras.law, + config: 512, + level: 1, + xp: 47.5, + recipe: { ingredients: [itemIds.talismans.law, itemIds.tiaras.blank] }, + }, + ], + [ + 'death', + { + id: itemIds.tiaras.death, + config: 1024, + level: 1, + xp: 50, + recipe: { ingredients: [itemIds.talismans.death, itemIds.tiaras.blank] }, + }, + ], ]); export const talismans: Map = new Map([ @@ -116,242 +155,326 @@ export const talismans: Map = new Map = new Map([ - ['air', { - entranceId: 2452, - craftingId: 2478, - portalId: 2465, - entrance: new Position(2841, 4829, 0), - exit: new Position(2983, 3292, 0) - }], - ['mind', { - entranceId: 2453, - craftingId: 2479, - portalId: 2466, - entrance: new Position(2793, 4828, 0), - exit: new Position(2980, 3514, 0) - }], - ['water', { - entranceId: 2454, - craftingId: 2480, - portalId: 2467, - entrance: new Position(2726, 4832, 0), - exit: new Position(3187, 3166, 0) - }], - ['earth', { - entranceId: 2455, - craftingId: 2481, - portalId: 2468, - entrance: new Position(2655, 4830, 0), - exit: new Position(3304, 3474, 0) - }], - ['fire', { - entranceId: 2456, - craftingId: 2482, - portalId: 2469, - entrance: new Position(2574, 4849, 0), - exit: new Position(3311, 3256, 0) - }], - ['body', { - entranceId: 2457, - craftingId: 2483, - portalId: 2470, - entrance: new Position(2524, 4825, 0), - exit: new Position(3051, 3445, 0) - }], - ['cosmic', { - entranceId: 2458, - craftingId: 2484, - portalId: 2471, - entrance: new Position(2142, 4813, 0), - exit: new Position(2408, 4379, 0) - }], - ['law', { - entranceId: 2459, - craftingId: 2485, - portalId: 2472, - entrance: new Position(2464, 4818, 0), - exit: new Position(2858, 3379, 0) - }], - ['nature', { - entranceId: 2460, - craftingId: 2486, - portalId: 2473, - entrance: new Position(2400, 4835, 0), - exit: new Position(2867, 3019, 0) - }], - ['chaos', { - entranceId: 2461, - craftingId: 2487, - portalId: 2474, - entrance: new Position(2268, 4842, 0), - exit: new Position(3058, 3591, 0) - }], - ['death', { - entranceId: 2462, - craftingId: 2488, - portalId: 2475, - entrance: new Position(2208, 4830, 0), - exit: new Position(3222, 3222, 0) - }], + [ + 'air', + { + entranceId: 2452, + craftingId: 2478, + portalId: 2465, + entrance: new Position(2841, 4829, 0), + exit: new Position(2983, 3292, 0), + }, + ], + [ + 'mind', + { + entranceId: 2453, + craftingId: 2479, + portalId: 2466, + entrance: new Position(2793, 4828, 0), + exit: new Position(2980, 3514, 0), + }, + ], + [ + 'water', + { + entranceId: 2454, + craftingId: 2480, + portalId: 2467, + entrance: new Position(2726, 4832, 0), + exit: new Position(3187, 3166, 0), + }, + ], + [ + 'earth', + { + entranceId: 2455, + craftingId: 2481, + portalId: 2468, + entrance: new Position(2655, 4830, 0), + exit: new Position(3304, 3474, 0), + }, + ], + [ + 'fire', + { + entranceId: 2456, + craftingId: 2482, + portalId: 2469, + entrance: new Position(2574, 4849, 0), + exit: new Position(3311, 3256, 0), + }, + ], + [ + 'body', + { + entranceId: 2457, + craftingId: 2483, + portalId: 2470, + entrance: new Position(2524, 4825, 0), + exit: new Position(3051, 3445, 0), + }, + ], + [ + 'cosmic', + { + entranceId: 2458, + craftingId: 2484, + portalId: 2471, + entrance: new Position(2142, 4813, 0), + exit: new Position(2408, 4379, 0), + }, + ], + [ + 'law', + { + entranceId: 2459, + craftingId: 2485, + portalId: 2472, + entrance: new Position(2464, 4818, 0), + exit: new Position(2858, 3379, 0), + }, + ], + [ + 'nature', + { + entranceId: 2460, + craftingId: 2486, + portalId: 2473, + entrance: new Position(2400, 4835, 0), + exit: new Position(2867, 3019, 0), + }, + ], + [ + 'chaos', + { + entranceId: 2461, + craftingId: 2487, + portalId: 2474, + entrance: new Position(2268, 4842, 0), + exit: new Position(3058, 3591, 0), + }, + ], + [ + 'death', + { + entranceId: 2462, + craftingId: 2488, + portalId: 2475, + entrance: new Position(2208, 4830, 0), + exit: new Position(3222, 3222, 0), + }, + ], ]); export const runes: Map = new Map([ - ['air', { - id: 556, - xp: 5.0, - level: 1, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('air'), - talisman: talismans.get('air'), - tiara: tiaras.get('air') - } as RunecraftingRune], - ['mind', { - id: 558, - xp: 5.5, - level: 1, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('mind'), - talisman: talismans.get('mind'), - tiara: tiaras.get('mind') - } as RunecraftingRune], - ['water', { - id: 555, - xp: 6, - level: 5, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('water'), - talisman: talismans.get('water'), - tiara: tiaras.get('water') - } as RunecraftingRune], - ['earth', { - id: 557, - xp: 6.5, - level: 9, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('earth'), - talisman: talismans.get('earth'), - tiara: tiaras.get('earth') - } as RunecraftingRune], - ['fire', { - id: 554, - xp: 7.0, - level: 14, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('fire'), - talisman: talismans.get('fire'), - tiara: tiaras.get('fire') - } as RunecraftingRune], - ['body', { - id: 559, - xp: 7.5, - level: 20, - essence: [itemIds.essence.pure, itemIds.essence.rune], - altar: altars.get('body'), - talisman: talismans.get('body'), - tiara: tiaras.get('body') - } as RunecraftingRune], - ['cosmic', { - id: 564, - xp: 8.0, - level: 27, - essence: [itemIds.essence.pure], - altar: altars.get('cosmic'), - talisman: talismans.get('cosmic'), - tiara: tiaras.get('cosmic') - } as RunecraftingRune], - ['chaos', { - id: 562, - xp: 8.5, - level: 35, - essence: [itemIds.essence.pure], - altar: altars.get('chaos'), - talisman: talismans.get('chaos'), - tiara: tiaras.get('chaos') - } as RunecraftingRune], - ['nature', { - id: 561, - xp: 9.0, - level: 44, - essence: [itemIds.essence.pure], - altar: altars.get('nature'), - talisman: talismans.get('nature'), - tiara: tiaras.get('nature') - } as RunecraftingRune], - ['law', { - id: 563, - xp: 9.5, - level: 54, - essence: [itemIds.essence.pure], - altar: altars.get('law'), - talisman: talismans.get('law'), - tiara: tiaras.get('law') - } as RunecraftingRune], - ['death', { - id: 560, - xp: 10.0, - level: 65, - essence: [itemIds.essence.pure], - altar: altars.get('death'), - talisman: talismans.get('death'), - tiara: tiaras.get('death') - } as RunecraftingRune], + [ + 'air', + { + id: 556, + xp: 5.0, + level: 1, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('air'), + talisman: talismans.get('air'), + tiara: tiaras.get('air'), + } as RunecraftingRune, + ], + [ + 'mind', + { + id: 558, + xp: 5.5, + level: 1, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('mind'), + talisman: talismans.get('mind'), + tiara: tiaras.get('mind'), + } as RunecraftingRune, + ], + [ + 'water', + { + id: 555, + xp: 6, + level: 5, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('water'), + talisman: talismans.get('water'), + tiara: tiaras.get('water'), + } as RunecraftingRune, + ], + [ + 'earth', + { + id: 557, + xp: 6.5, + level: 9, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('earth'), + talisman: talismans.get('earth'), + tiara: tiaras.get('earth'), + } as RunecraftingRune, + ], + [ + 'fire', + { + id: 554, + xp: 7.0, + level: 14, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('fire'), + talisman: talismans.get('fire'), + tiara: tiaras.get('fire'), + } as RunecraftingRune, + ], + [ + 'body', + { + id: 559, + xp: 7.5, + level: 20, + essence: [itemIds.essence.pure, itemIds.essence.rune], + altar: altars.get('body'), + talisman: talismans.get('body'), + tiara: tiaras.get('body'), + } as RunecraftingRune, + ], + [ + 'cosmic', + { + id: 564, + xp: 8.0, + level: 27, + essence: [itemIds.essence.pure], + altar: altars.get('cosmic'), + talisman: talismans.get('cosmic'), + tiara: tiaras.get('cosmic'), + } as RunecraftingRune, + ], + [ + 'chaos', + { + id: 562, + xp: 8.5, + level: 35, + essence: [itemIds.essence.pure], + altar: altars.get('chaos'), + talisman: talismans.get('chaos'), + tiara: tiaras.get('chaos'), + } as RunecraftingRune, + ], + [ + 'nature', + { + id: 561, + xp: 9.0, + level: 44, + essence: [itemIds.essence.pure], + altar: altars.get('nature'), + talisman: talismans.get('nature'), + tiara: tiaras.get('nature'), + } as RunecraftingRune, + ], + [ + 'law', + { + id: 563, + xp: 9.5, + level: 54, + essence: [itemIds.essence.pure], + altar: altars.get('law'), + talisman: talismans.get('law'), + tiara: tiaras.get('law'), + } as RunecraftingRune, + ], + [ + 'death', + { + id: 560, + xp: 10.0, + level: 65, + essence: [itemIds.essence.pure], + altar: altars.get('death'), + talisman: talismans.get('death'), + tiara: tiaras.get('death'), + } as RunecraftingRune, + ], ]); export const combinationRunes: Map = new Map([ - ['mist', { - altar: [altars.get('air'), altars.get('water')], - id: 4695, - level: 7, - talisman: [talismans.get('air'), talismans.get('water')], - tiara: [tiaras.get('air'), tiaras.get('water')], - runes: [runes.get('air'), runes.get('water')], - xp: [8.0, 8.5] - } as RunecraftingCombinationRune], - ['dust', { - id: 4696, - level: 10, - xp: [8.3, 9.0], - altar: [altars.get('air'), altars.get('earth')], - talisman: [talismans.get('air'), talismans.get('earth')], - runes: [runes.get('air'), runes.get('earth')], - tiara: [tiaras.get('air'), tiaras.get('earth')], - } as RunecraftingCombinationRune], - ['mud', { - id: 4698, - level: 13, - xp: [9.3, 9.5], - altar: [altars.get('water'), altars.get('earth')], - talisman: [talismans.get('water'), talismans.get('earth')], - runes: [runes.get('water'), runes.get('earth')], - tiara: [tiaras.get('water'), tiaras.get('earth')], - } as RunecraftingCombinationRune], - ['smoke', { - id: 4697, - level: 15, - xp: [8.5, 9.5], - altar: [altars.get('air'), altars.get('fire')], - talisman: [talismans.get('air'), talismans.get('fire')], - runes: [runes.get('air'), runes.get('fire')], - tiara: [tiaras.get('air'), tiaras.get('fire')], - } as RunecraftingCombinationRune], - ['steam', { - id: 4694, - level: 19, - xp: [9.5, 10.0], - altar: [altars.get('water'), altars.get('fire')], - talisman: [talismans.get('water'), talismans.get('fire')], - runes: [runes.get('water'), runes.get('fire')], - tiara: [tiaras.get('water'), tiaras.get('fire')], - } as RunecraftingCombinationRune], - ['lava', { - id: 4699, - level: 23, - xp: [10.0, 10.5], - altar: [altars.get('earth'), altars.get('fire')], - talisman: [talismans.get('earth'), talismans.get('fire')], - runes: [runes.get('earth'), runes.get('fire')], - tiara: [tiaras.get('earth'), tiaras.get('fire')], - } as RunecraftingCombinationRune], + [ + 'mist', + { + altar: [altars.get('air'), altars.get('water')], + id: 4695, + level: 7, + talisman: [talismans.get('air'), talismans.get('water')], + tiara: [tiaras.get('air'), tiaras.get('water')], + runes: [runes.get('air'), runes.get('water')], + xp: [8.0, 8.5], + } as RunecraftingCombinationRune, + ], + [ + 'dust', + { + id: 4696, + level: 10, + xp: [8.3, 9.0], + altar: [altars.get('air'), altars.get('earth')], + talisman: [talismans.get('air'), talismans.get('earth')], + runes: [runes.get('air'), runes.get('earth')], + tiara: [tiaras.get('air'), tiaras.get('earth')], + } as RunecraftingCombinationRune, + ], + [ + 'mud', + { + id: 4698, + level: 13, + xp: [9.3, 9.5], + altar: [altars.get('water'), altars.get('earth')], + talisman: [talismans.get('water'), talismans.get('earth')], + runes: [runes.get('water'), runes.get('earth')], + tiara: [tiaras.get('water'), tiaras.get('earth')], + } as RunecraftingCombinationRune, + ], + [ + 'smoke', + { + id: 4697, + level: 15, + xp: [8.5, 9.5], + altar: [altars.get('air'), altars.get('fire')], + talisman: [talismans.get('air'), talismans.get('fire')], + runes: [runes.get('air'), runes.get('fire')], + tiara: [tiaras.get('air'), tiaras.get('fire')], + } as RunecraftingCombinationRune, + ], + [ + 'steam', + { + id: 4694, + level: 19, + xp: [9.5, 10.0], + altar: [altars.get('water'), altars.get('fire')], + talisman: [talismans.get('water'), talismans.get('fire')], + runes: [runes.get('water'), runes.get('fire')], + tiara: [tiaras.get('water'), tiaras.get('fire')], + } as RunecraftingCombinationRune, + ], + [ + 'lava', + { + id: 4699, + level: 23, + xp: [10.0, 10.5], + altar: [altars.get('earth'), altars.get('fire')], + talisman: [talismans.get('earth'), talismans.get('fire')], + runes: [runes.get('earth'), runes.get('fire')], + tiara: [tiaras.get('earth'), tiaras.get('fire')], + } as RunecraftingCombinationRune, + ], ]); export function getEntityByAttr(entities: Map, attr: string, value: unknown): T | null { @@ -360,15 +483,19 @@ export function getEntityByAttr(entities: Map, attr: string, value: u // Handles dot seperated attribute names. if (splits.length === 2) { - entities.forEach((e) => { - if (e[splits[0]][splits[1]] === value) { entity = e; } + entities.forEach(e => { + if (e[splits[0]][splits[1]] === value) { + entity = e; + } }); } // Handles single attribute name. if (splits.length === 1) { - entities.forEach((e) => { - if (e[attr] === value) { entity = e; } + entities.forEach(e => { + if (e[attr] === value) { + entity = e; + } }); } @@ -376,28 +503,40 @@ export function getEntityByAttr(entities: Map, attr: string, value: u } export function getEntityIds(entities: Map, property: keyof T): number[] { - const entityIds : number[] = []; + const entityIds: number[] = []; entities.forEach((entity: T) => { - if(entity[property] && typeof entity[property] === 'number') { + if (entity[property] && typeof entity[property] === 'number') { const tempnum: number = entity[property] as any; entityIds.push(tempnum); } - }); return entityIds; + }); + return entityIds; } export function runeMultiplier(runeId: number, level: number): number { switch (runeId) { - case 556: return (Math.floor((level / 11.0)) + 1); - case 558: return (Math.floor((level / 14.0)) + 1); - case 555: return (Math.floor((level / 19.0)) + 1); - case 557: return (Math.floor((level / 26.0)) + 1); - case 554: return (Math.floor((level / 35.0)) + 1); - case 559: return (Math.floor((level / 46.0)) + 1); - case 564: return (Math.floor((level / 59.0)) + 1); - case 562: return (Math.floor((level / 74.0)) + 1); - case 561: return (Math.floor((level / 91.0)) + 1); - case 563: return 1.0; - case 560: return 1.0; + case 556: + return Math.floor(level / 11.0) + 1; + case 558: + return Math.floor(level / 14.0) + 1; + case 555: + return Math.floor(level / 19.0) + 1; + case 557: + return Math.floor(level / 26.0) + 1; + case 554: + return Math.floor(level / 35.0) + 1; + case 559: + return Math.floor(level / 46.0) + 1; + case 564: + return Math.floor(level / 59.0) + 1; + case 562: + return Math.floor(level / 74.0) + 1; + case 561: + return Math.floor(level / 91.0) + 1; + case 563: + return 1.0; + case 560: + return 1.0; } return 1.0; diff --git a/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts index 915894755..6929db0c6 100644 --- a/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts @@ -1,21 +1,22 @@ +import type { ItemOnObjectAction, itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; +import type { ObjectInteractionAction, objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { randomBetween } from '@engine/util/num'; /** * @Author NickNick */ import { Skill } from '@engine/world/actor/skills'; +import { itemIds } from '@engine/world/config/item-ids'; import { - altars, combinationRunes, + altars, + combinationRunes, getEntityByAttr, - getEntityIds, runeMultiplier, + getEntityIds, + runeMultiplier, runes, } from '@plugins/skills/runecrafting/runecrafting-constants'; import type { RunecraftingCombinationRune } from '@plugins/skills/runecrafting/runecrafting-types'; -import { randomBetween } from '@engine/util/num'; -import { itemIds } from '@engine/world/config/item-ids'; -import { findItem, widgets } from '@engine/config/config-handler'; import { logger } from '@runejs/common'; -import type { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/action/pipe/item-on-object.action'; -import type { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action/pipe/object-interaction.action'; - const craftRune: objectInteractionActionHandler = (details: ObjectInteractionAction) => { const { player, object } = details; @@ -39,21 +40,21 @@ const craftRune: objectInteractionActionHandler = (details: ObjectInteractionAct return; } let essenceAvailable = 0; - rune.essence.forEach((essenceId) => { + rune.essence.forEach(essenceId => { essenceAvailable += player.inventory.findAll(essenceId).length; }); if (essenceAvailable > 0) { // Remove essence from inventory. - rune.essence.forEach((essenceId) => { - player.inventory.findAll(essenceId).forEach((index) => { + rune.essence.forEach(essenceId => { + player.inventory.findAll(essenceId).forEach(index => { player.inventory.remove(index); }); }); // Add crafted runes to inventory. - player.inventory.add({ itemId: rune.id, amount: (runeMultiplier(rune.id, level) * essenceAvailable) }); + player.inventory.add({ itemId: rune.id, amount: runeMultiplier(rune.id, level) * essenceAvailable }); // Add experience - player.skills.addExp(Skill.RUNECRAFTING, (rune.xp * essenceAvailable)); + player.skills.addExp(Skill.RUNECRAFTING, rune.xp * essenceAvailable); // Update widget items. player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); return; @@ -64,7 +65,7 @@ const craftRune: objectInteractionActionHandler = (details: ObjectInteractionAct function getCombinationRuneByAltar(itemId: number, objectId: number): RunecraftingCombinationRune | undefined { for (const combinationRune of combinationRunes.values()) { - const altarIndex = combinationRune.altar.findIndex((altar) => altar.craftingId === objectId); + const altarIndex = combinationRune.altar.findIndex(altar => altar.craftingId === objectId); if (altarIndex > -1 && combinationRune.talisman[altarIndex ^ 1].id === itemId) { return combinationRune; } @@ -111,7 +112,7 @@ const craftCombinationRune: itemOnObjectActionHandler = (details: ItemOnObjectAc } else { player.inventory.set(requiredRunesIndex, { itemId: rune.runes[altarIndex ^ 1].id, - amount: requiredRunesAvailable - amountToCraft + amount: requiredRunesAvailable - amountToCraft, }); } // Remove essence from inventory. @@ -121,7 +122,7 @@ const craftCombinationRune: itemOnObjectActionHandler = (details: ItemOnObjectAc // Add crafted runes to inventory. player.inventory.add({ itemId: rune.id, amount: amountToCraft }); // Add experience - player.skills.addExp(Skill.RUNECRAFTING, (rune.xp[altarIndex] * essenceAvailable)); + player.skills.addExp(Skill.RUNECRAFTING, rune.xp[altarIndex] * essenceAvailable); if (shouldBreakTalisman) { player.inventory.removeFirst(item.itemId); } @@ -134,7 +135,6 @@ const craftCombinationRune: itemOnObjectActionHandler = (details: ItemOnObjectAc player.sendMessage(`You do not have any pure essence to bind.`); }; - export default { pluginId: 'rs:runecrafting', hooks: [ @@ -142,13 +142,13 @@ export default { type: 'object_interaction', objectIds: getEntityIds(altars, 'craftingId'), walkTo: true, - handler: craftRune + handler: craftRune, }, { type: 'item_on_object', objectIds: getEntityIds(altars, 'craftingId'), walkTo: true, - handler: craftCombinationRune - } - ] + handler: craftCombinationRune, + }, + ], }; diff --git a/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts index 57c9a85d8..b05ad6daf 100644 --- a/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts @@ -6,13 +6,12 @@ import type { equipmentChangeActionHandler } from '@engine/action/pipe/equipment import { getEntityByAttr, getEntityIds, tiaras } from '@plugins/skills/runecrafting/runecrafting-constants'; import { logger } from '@runejs/common'; - -const unequipTiara : equipmentChangeActionHandler = (details) => { +const unequipTiara: equipmentChangeActionHandler = details => { const { player } = details; player.outgoingPackets.updateClientConfig(491, 0); }; -const equipTiara : equipmentChangeActionHandler = (details) => { +const equipTiara: equipmentChangeActionHandler = details => { const { player, itemId } = details; const tiara = getEntityByAttr(tiaras, 'id', itemId); @@ -24,9 +23,6 @@ const equipTiara : equipmentChangeActionHandler = (details) => { player.outgoingPackets.updateClientConfig(491, tiara.config); }; - - - export default { pluginId: 'rs:runecrafting_tiaras', hooks: [ @@ -34,12 +30,13 @@ export default { type: 'equipment_change', eventType: 'equip', itemIds: getEntityIds(tiaras, 'id'), - handler: equipTiara - }, { + handler: equipTiara, + }, + { type: 'equipment_change', eventType: 'unequip', itemIds: getEntityIds(tiaras, 'id'), - handler: unequipTiara - } - ] + handler: unequipTiara, + }, + ], }; diff --git a/src/plugins/skills/skill-guides/Strength.json b/src/plugins/skills/skill-guides/Strength.json index 6ce82212c..4707cd2b6 100644 --- a/src/plugins/skills/skill-guides/Strength.json +++ b/src/plugins/skills/skill-guides/Strength.json @@ -1,72 +1,72 @@ { - "id": 121, - "name": "Strength", - "members": false, - "sub_guides": [ - { - "name": "Weapons", - "lines": [ + "id": 121, + "name": "Strength", + "members": false, + "sub_guides": [ { - "item": "rs:black_halberd", - "text": "Black halberd\\n(10 Attack is needed)", - "level": 5 + "name": "Weapons", + "lines": [ + { + "item": "rs:black_halberd", + "text": "Black halberd\\n(10 Attack is needed)", + "level": 5 + }, + { + "item": "rs:white_halberd", + "text": "White halberd\\n(10 Attack is needed)", + "level": 5 + }, + { + "item": "rs:mithril_halberd", + "text": "Mithril halberd\\n(20 Attack is needed)", + "level": 10 + }, + { + "item": "rs:adamant_halberd", + "text": "Adamant halberd\\n(30 Attack is needed)", + "level": 15 + }, + { + "item": "rs:rune_halberd", + "text": "Rune halberd\\n(40 Attack is needed)", + "level": 20 + }, + { + "item": "rs:dragon_halberd", + "text": "Dragon halberd\\n(60 Attack is needed)", + "level": 30 + }, + { + "item": "rs:granite_maul", + "text": "Granite maul\\n(50 Attack is needed)", + "level": 50 + }, + { + "item": "rs:tzhaar-ket-om", + "text": "TzHaar-Ket-Om\\nobsidian maul", + "level": 60 + }, + { + "item": "rs:dharoks_greataxe", + "text": "Dharok's greataxe\\n(70 Attack is needed)", + "level": 70 + }, + { + "item": "rs:torags_hammers", + "text": "Torag's hammers\\n(70 Attack is needed)", + "level": 70 + } + ] }, { - "item": "rs:white_halberd", - "text": "White halberd\\n(10 Attack is needed)", - "level": 5 - }, - { - "item": "rs:mithril_halberd", - "text": "Mithril halberd\\n(20 Attack is needed)", - "level": 10 - }, - { - "item": "rs:adamant_halberd", - "text": "Adamant halberd\\n(30 Attack is needed)", - "level": 15 - }, - { - "item": "rs:rune_halberd", - "text": "Rune halberd\\n(40 Attack is needed)", - "level": 20 - }, - { - "item": "rs:dragon_halberd", - "text": "Dragon halberd\\n(60 Attack is needed)", - "level": 30 - }, - { - "item": "rs:granite_maul", - "text": "Granite maul\\n(50 Attack is needed)", - "level": 50 - }, - { - "item": "rs:tzhaar-ket-om", - "text": "TzHaar-Ket-Om\\nobsidian maul", - "level": 60 - }, - { - "item": "rs:dharoks_greataxe", - "text": "Dharok's greataxe\\n(70 Attack is needed)", - "level": 70 - }, - { - "item": "rs:torags_hammers", - "text": "Torag's hammers\\n(70 Attack is needed)", - "level": 70 - } - ] - }, - { - "name": "Armour", - "lines": [ - { - "item": "rs:granite", - "text": "Granite Armour", - "level": 50 + "name": "Armour", + "lines": [ + { + "item": "rs:granite", + "text": "Granite Armour", + "level": 50 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/attack.json b/src/plugins/skills/skill-guides/attack.json index cd7320ed5..4983f9d17 100644 --- a/src/plugins/skills/skill-guides/attack.json +++ b/src/plugins/skills/skill-guides/attack.json @@ -1,97 +1,97 @@ { - "id": 118, - "name": "Attack", - "members": false, - "sub_guides": [ - { - "name": "Weapons", - "lines": [ - { - "item": "rs:bronze_dagger", - "text": "Bronze", - "level": 1 - }, - { - "item": "rs:iron_dagger", - "text": "Iron", - "level": 1 - }, - { - "item": "rs:steel_dagger", - "text": "Steel", - "level": 5 - }, - { - "item": "rs:black_dagger", - "text": "Black", - "level": 10 - }, - { - "item": "rs:white_dagger", - "text": "Members: White", - "level": 10 - }, - { - "item": "rs:mithril_dagger", - "text": "Mithril", - "level": 20 - }, - { - "item": "rs:adamant_dagger", - "text": "Adamant", - "level": 30 - }, - { - "item": "rs:battlestaff", - "text": "Members: Battlestaves (with 30 Magic)", - "level": 30 - }, - { - "item": "rs:rune_dagger", - "text": "Rune", - "level": 40 - }, - { - "item": "rs:granite_maul", - "text": "Members: Granite Maul", - "level": 50 - }, - { - "item": "rs:dragon_dagger", - "text": "Members: Dragon", - "level": 60 - }, - { - "item": "rs:toktz_xil_ak", - "text": "Members: Obsidian weapons", - "level": 60 - }, - { - "item": "rs:abyssal_whip", - "text": "Members: Abyssal Whip", - "level": 70 - }, - { - "item": "rs:dharoks_greataxe", - "text": "Members: Dharok's greataxe", - "level": 70 - }, - { - "item": "rs:torags_hammers", - "text": "Members: Torag's hammers", - "level": 70 - }, - { - "item": "rs:veracs_flail", - "text": "Members: Verac's flail", - "level": 70 - }, - { - "item": "rs:guthans_warspear", - "text": "Members: Guthan's warspear", - "level": 70 + "id": 118, + "name": "Attack", + "members": false, + "sub_guides": [ + { + "name": "Weapons", + "lines": [ + { + "item": "rs:bronze_dagger", + "text": "Bronze", + "level": 1 + }, + { + "item": "rs:iron_dagger", + "text": "Iron", + "level": 1 + }, + { + "item": "rs:steel_dagger", + "text": "Steel", + "level": 5 + }, + { + "item": "rs:black_dagger", + "text": "Black", + "level": 10 + }, + { + "item": "rs:white_dagger", + "text": "Members: White", + "level": 10 + }, + { + "item": "rs:mithril_dagger", + "text": "Mithril", + "level": 20 + }, + { + "item": "rs:adamant_dagger", + "text": "Adamant", + "level": 30 + }, + { + "item": "rs:battlestaff", + "text": "Members: Battlestaves (with 30 Magic)", + "level": 30 + }, + { + "item": "rs:rune_dagger", + "text": "Rune", + "level": 40 + }, + { + "item": "rs:granite_maul", + "text": "Members: Granite Maul", + "level": 50 + }, + { + "item": "rs:dragon_dagger", + "text": "Members: Dragon", + "level": 60 + }, + { + "item": "rs:toktz_xil_ak", + "text": "Members: Obsidian weapons", + "level": 60 + }, + { + "item": "rs:abyssal_whip", + "text": "Members: Abyssal Whip", + "level": 70 + }, + { + "item": "rs:dharoks_greataxe", + "text": "Members: Dharok's greataxe", + "level": 70 + }, + { + "item": "rs:torags_hammers", + "text": "Members: Torag's hammers", + "level": 70 + }, + { + "item": "rs:veracs_flail", + "text": "Members: Verac's flail", + "level": 70 + }, + { + "item": "rs:guthans_warspear", + "text": "Members: Guthan's warspear", + "level": 70 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/construction.json b/src/plugins/skills/skill-guides/construction.json index 693ddd41b..c88bc748f 100644 --- a/src/plugins/skills/skill-guides/construction.json +++ b/src/plugins/skills/skill-guides/construction.json @@ -3,2273 +3,2290 @@ "name": "Construction", "members": true, "sub_guides": [ - { - "name": "Rooms", - "lines": [ - { - "item": "rs:garden", - "text": "Garden", - "level": 1 - }, - { - "item": "rs:parlour", - "text": "Parlour", - "level": 1 - }, - { - "item": "rs:kitchen", - "text": "Kitchen", - "level": 5 - }, - { - "item": "rs:dining_room", - "text": "Dining room", - "level": 10 - }, - { - "item": "rs:workshop", - "text": "Workshop", - "level": 15 - }, - { - "item": "rs:bedroom", - "text": "Bedroom", - "level": 20 - }, - { - "item": "rs:hall_skill_trophies", - "text": "Hall (skill trophies)", - "level": 25 - }, - { - "item": "rs:league_hall", - "text": "Leauge hall", - "level": 27 - }, - { - "item": "rs:games_room", - "text": "Games room", - "level": 30 - }, - { - "item": "rs:combat_room", - "text": "Combat room", - "level": 32 - }, - { - "item": "rs:hall_quest_trophies", - "text": "Hall (quest trophies)", - "level": 35 - }, - { - "item": "rs:menagerie", - "text": "Menagerie", - "level": 37 - }, - { - "item": "rs:study", - "text": "Study", - "level": 40 - }, - { - "item": "rs:costume_room", - "text": "Costume room", - "level": 42 - }, - { - "item": "rs:chapel", - "text": "Chapel", - "level": 45 - }, - { - "item": "rs:portal_chamber", - "text": "Portal chamber", - "level": 50 - }, - { - "item": "rs:formal_garden", - "text": "Formal garden", - "level": 55 - }, - { - "item": "rs:throne_room", - "text": "Throne room", - "level": 60 - }, - { - "item": "rs:oubliette", - "text": "Oubliette", - "level": 65 - }, - { - "item": "rs:superior_garden", - "text": "Superior garden", - "level": 65 - }, - { - "item": "rs:dungeon", - "text": "Dungeon", - "level": 70 - }, - { - "item": "rs:treasure_room", - "text": "Treasure room", - "level": 75 - }, - { - "item": "rs:achievement_gallery", - "text": "Achievement Gallery", - "level": 80 - }, - { - "item": "rs:league_hall", - "text": "Garden", - "level": 1 - } - ] - },{ - "name": "Skills", - "lines": [ - { - "item": "rs:clay_fireplace", - "text": "Clay fireplace", - "level": 3 - }, - { - "item": "rs:firepit", - "text": "Firepit", - "level": 5 - }, - { - "item": "rs:pump_and_drain", - "text": "Pump and drain", - "level": 7 - }, - { - "item": "rs:firepit_with_hook", - "text": "Firepit with hook", - "level": 11 - }, - { - "item": "rs:repair_bench", - "text": "Repair bench", - "level": 15 - }, - { - "item": "rs:pluming_stand", - "text": "Pluming stand", - "level": 16 - }, - { - "item": "rs:crafting_table_1", - "text": "Crafting table 1", - "level": 16 - }, - { - "item": "rs:firepit_with_pot", - "text": "Firepit with pot", - "level": 17 - }, - { - "item": "rs:wooden_workbench", - "text": "Wooden workbench", - "level": 17 - }, - { - "item": "rs:small_oven", - "text": "Small oven", - "level": 24 - }, - { - "item": "rs:crafting_table_2", - "text": "Crafting table 2", - "level": 25 - }, - { - "item": "rs:pump_and_tub", - "text": "Pump and tub", - "level": 27 - }, - { - "item": "rs:large_oven", - "text": "Large oven", - "level": 29 - }, - { - "item": "rs:oak_workbench", - "text": "Oak workbench", - "level": 32 - }, - { - "item": "rs:stone_fireplace", - "text": "Stone fireplace", - "level": 33 - }, - { - "item": "rs:crafting_table_3", - "text": "Crafting table 3", - "level": 34 - }, - { - "item": "rs:steel_range", - "text": "Steel range", - "level": 34 - }, - { - "item": "rs:whetstone", - "text": "Whetstone", - "level": 35 - }, - { - "item": "rs:shield_easel", - "text": "Shield easel", - "level": 41 - }, - { - "item": "rs:fancy_range", - "text": "Fancy range", - "level": 42 - }, - { - "item": "rs:crafting_table_4", - "text": "Crafting table 4", - "level": 42 - }, - { - "item": "rs:steel_framed_workbench", - "text": "Steel framed workbench", - "level": 46 - }, - { - "item": "rs:sink", - "text": "Sink", - "level": 47 - }, - { - "item": "rs:armour_stand", - "text": "Armour stand", - "level": 55 - }, - { - "item": "rs:workbench_with_vice", - "text": "Workbench with vice", - "level": 62 - }, - { - "item": "rs:marble_fireplace", - "text": "Marble fireplace", - "level": 63 - }, - { - "item": "rs:banner_easel", - "text": "Banner easel", - "level": 66 - }, - { - "item": "rs:workbench_with_lathe", - "text": "Workbench with lathe", - "level": 77 - }, - { - "item": "rs:ancient_altar", - "text": "Ancient altar", - "level": 80 - }, - { - "item": "rs:lunar_altar", - "text": "Lunar altar", - "level": 80 - }, - { - "item": "rs:dark_altar", - "text": "Dark altar", - "level": 80 - } - ] - },{ - "name": "Surfaces", - "lines": [ - { - "item": "rs:crude_wooden_chair", - "text": "Crude wooden chair", - "level": 1 - }, - { - "item": "rs:wooden_chair", - "text": "Wooden chair", - "level": 8 - }, - { - "item": "rs:wooden_dining_table", - "text": "Wooden dining table", - "level": 10 - }, - { - "item": "rs:wooden_kitchen_table", - "text": "Wooden kitchen table", - "level": 12 - }, - { - "item": "rs:rocking_chair", - "text": "Rocking chair", - "level": 14 - }, - { - "item": "rs:oak_chair", - "text": "Oak chair", - "level": 19 - }, - { - "item": "rs:wooden_bed", - "text": "Wooden bed", - "level": 20 - }, - { - "item": "rs:oak_dining_table", - "text": "Oak dining table", - "level": 22 - }, - { - "item": "rs:oak_dining_bench", - "text": "Oak dining bench", - "level": 22 - }, - { - "item": "rs:oak_armchair", - "text": "Oak armchair", - "level": 26 - }, - { - "item": "rs:oak_bed", - "text": "Oak bed", - "level": 30 - }, - { - "item": "rs:carved_oak_dining_table", - "text": "Carved oak dining table", - "level": 31 - }, - { - "item": "rs:carved_oak_dining_bench", - "text": "Carved oak dining bench", - "level": 31 - }, - { - "item": "rs:oak_kitchen_table", - "text": "Oak kitchen table", - "level": 32 - }, - { - "item": "rs:large_oak_bed", - "text": "Large oak bed", - "level": 34 - }, - { - "item": "rs:teak_armchair", - "text": "Teak armchair", - "level": 35 - }, - { - "item": "rs:teak_dining_table", - "text": "Teak dining table", - "level": 38 - }, - { - "item": "rs:teak_dining_bench", - "text": "Teak dining bench", - "level": 38 - }, - { - "item": "rs:teak_bed", - "text": "Teak bed", - "level": 40 - }, - { - "item": "rs:carved_teak_dining_bench", - "text": "Carved teak dining bench", - "level": 44 - }, - { - "item": "rs:carved_teak_dining_table", - "text": "Carved teak dining table", - "level": 45 - }, - { - "item": "rs:large_teak_bed", - "text": "Large teak bed", - "level": 45 - }, - { - "item": "rs:mahogany_armchair", - "text": "Mahogany armchair", - "level": 50 - }, - { - "item": "rs:mahogany_dining_table", - "text": "Mahogany dining table", - "level": 52 - }, - { - "item": "rs:mahogany_dining_bench", - "text": "Mahogany dining bench", - "level": 52 - }, - { - "item": "rs:teak_kitchen_table", - "text": "Teak kitchen table", - "level": 52 - }, - { - "item": "rs:mahogany_four_poster_bed", - "text": "Mahogany four-poster bed", - "level": 53 - }, - { - "item": "rs:oak_throne", - "text": "Oak throne", - "level": 60 - }, - { - "item": "rs:gilded_mahogany_four_poster_bed", - "text": "Gilded mahogany four-poster bed", - "level": 60 - }, - { - "item": "rs:gilded_mahogany_dining_bench", - "text": "Gilded mahogany dining bench", - "level": 61 - }, - { - "item": "rs:teak_throne", - "text": "Teak throne", - "level": 67 - }, - { - "item": "rs:gilded_mahogany_and_marble_table", - "text": "Gilded mahogany and marble table", - "level": 72 - }, - { - "item": "rs:mahogany_throne", - "text": "Mahogany throne", - "level": 74 - }, - { - "item": "rs:gilded_mahogany_throne", - "text": "Gilded mahogany throne", - "level": 81 - }, - { - "item": "rs:teak_kitchen_table", - "text": "Teak kitchen table", - "level": 52 - }, - { - "item": "rs:teak_kitchen_table", - "text": "Teak kitchen table", - "level": 52 - }, - { - "item": "rs:teak_kitchen_table", - "text": "Teak kitchen table", - "level": 52 - }, - { - "item": "rs:skeleton_throne", - "text": "Skeleton throne", - "level": 88 - }, - { - "item": "rs:crystal_throne", - "text": "Crystal throne", - "level": 95 - }, - { - "item": "rs:demonic_throne", - "text": "Demonic throne", - "level": 99 - } - ] - } ,{ - "name": "Storage", - "lines": [ - { - "item": "rs:wooden_bookcase", - "text": "Wooden bookcase", - "level": 4 - }, - { - "item": "rs:wooden_shelves_1", - "text": "Wooden shelves 1", - "level": 6 - }, - { - "item": "rs:beer_barrel", - "text": "Beer barrel", - "level": 7 - }, - { - "item": "rs:wooden_larder", - "text": "Wooden larder", - "level": 9 - }, - { - "item": "rs:cider_barrel", - "text": "Cider barrel", - "level": 12 - }, - { - "item": "rs:wooden_shelves_2", - "text": "Wooden shelves 2", - "level": 12 - }, - { - "item": "rs:tool_store_1", - "text": "Tool store 1", - "level": 15 - }, - { - "item": "rs:asgarnian_ale_barrel", - "text": "Asgarnian ale barrel", - "level": 18 - }, - { - "item": "rs:shoe_box", - "text": "Shoe box", - "level": 20 - }, - { - "item": "rs:wooden_shaving_stand", - "text": "Wooden shaving stand", - "level": 21 - }, - { - "item": "rs:wooden_shelves_3", - "text": "Wooden shelves 3", - "level": 23 - }, - { - "item": "rs:tool_store_2", - "text": "Tool store 2", - "level": 25 - }, - { - "item": "rs:greenmans_ale_barrel", - "text": "Greenman's Ale barrel", - "level": 26 - }, - { - "item": "rs:oak_chest_of_drawers", - "text": "oak chest of drawers", - "level": 27 - }, - { - "item": "rs:oak_bookcase", - "text": "Oak bookcase", - "level": 29 - }, - { - "item": "rs:oak_shaving_stand", - "text": "Oak shaving stand", - "level": 29 - }, - { - "item": "rs:oak_larder", - "text": "Oak larder", - "level": 33 - }, - { - "item": "rs:oak_shelves_1", - "text": "Oak shelves 1", - "level": 34 - }, - { - "item": "rs:tool_store_3", - "text": "Tool store 3", - "level": 35 - }, - { - "item": "rs:dragon_bitter_barrel", - "text": "Dragon Bitter barrel", - "level": 36 - }, - { - "item": "rs:oak_dresser", - "text": "Oak dresser", - "level": 37 - }, - { - "item": "rs:oak_Wardrobe_bedroom", - "text": "Oak wardrobe (bedroom)", - "level": 39 - }, - { - "item": "rs:mahogany_bookcase", - "text": "Mahogany bookcase", - "level": 40 - }, - { - "item": "rs:oak_wardrobe_costume_room", - "text": "Oak wardrobe (costtume room)", - "level": 15 - }, - { - "item": "rs:teak_larder", - "text": "Teak larder", - "level": 43 - }, - { - "item": "rs:oak_fancy_dress_box", - "text": "Oak fancy dress box", - "level": 44 - }, - { - "item": "rs:tool_store_4", - "text": "Tool store 4", - "level": 44 - }, - { - "item": "rs:oak_shelves_2", - "text": "Oak shelves 2", - "level": 45 - }, - { - "item": "rs:oak_armour_case", - "text": "Oak armour case", - "level": 46 - }, - { - "item": "rs:teak_dresser", - "text": "Teak dresser", - "level": 46 - }, - { - "item": "rs:chefs_delight_barrel", - "text": "Chef's Delight barrel", - "level": 48 - }, - { - "item": "rs:oak_treasure_chest", - "text": "Oak treasure chest", - "level": 48 - }, - { - "item": "rs:oak_toy_box", - "text": "Oak toy box", - "level": 50 - }, - { - "item": "rs:carved_oak_wardrobe_costume_room", - "text": "Carved oak wardrobe (costume room)", - "level": 51 - }, - { - "item": "rs:teak_chest_of_drawers", - "text": "Teak chest of drawers", - "level": 51 - }, - { - "item": "rs:oak_cape_rack", - "text": "Oak cape rack", - "level": 54 - }, - { - "item": "rs:tool_store_5", - "text": "Tool store 5", - "level": 55 - }, - { - "item": "rs:teak_shelves_1", - "text": "Teak shelves 1", - "level": 56 - }, - { - "item": "rs:fancy_teak_dresser", - "text": "Fancy teak dresser", - "level": 56 - }, - { - "item": "rs:servants_moneybag", - "text": "Servant's moneybag", - "level": 58 - }, - { - "item": "rs:teak_wardrobe_costume_room", - "text": "Teak wardrobe (costume room)", - "level": 60 - }, - { - "item": "rs:spice_rack", - "text": "Spice Rack", - "level": 60 - }, - { - "item": "rs:teak_fancy_dress_box", - "text": "Teak fancy dress box", - "level": 62 - }, - { - "item": "rs:teak_cape_rack", - "text": "Teak cape rack", - "level": 63 - }, - { - "item": "rs:teak_wardrobe_bedroom", - "text": "Teak wardrobe (bedroom)", - "level": 63 - }, - { - "item": "rs:teak_armour_case", - "text": "Teak armour case", - "level": 64 - }, - { - "item": "rs:mahogany_dresser", - "text": "Mahogany dresser", - "level": 64 - }, - { - "item": "rs:teak_treasure_chest", - "text": "Teak treasure chest", - "level": 66 - }, - { - "item": "rs:teak_toy_box", - "text": "Teak toyo boy", - "level": 68 - }, - { - "item": "rs:carved_teak_wardrobe_costume_room", - "text": "Carved teak wardrobe (costume room)", - "level": 69 - }, - { - "item": "rs:mahogany_cape_rack", - "text": "Mahogany cape rack", - "level": 72 - }, - { - "item": "rs:gilded_mahogany_dresser", - "text": "Gilded mahogany dresser", - "level": 74 - }, - { - "item": "rs:mahogany_wardrobe_bedroom", - "text": "Mahogany wardrobe (bedroom)", - "level": 75 - }, - { - "item": "rs:mahogany_wardrobe_costume_room", - "text": "Mahogany wardrobe (costume room)", - "level": 78 - }, - { - "item": "rs:mahogany_fancy_dress_box", - "text": "Mahogany fancy dress box", - "level": 80 - }, - { - "item": "rs:basic_jewellery_box", - "text": "Basic jewellery box", - "level": 81 - }, - { - "item": "rs:gilded_mahogany_cape_rack", - "text": "Gilded mahogany cape rack", - "level": 81 - }, - { - "item": "rs:mahogany_armour_case", - "text": "Mahogany armour case", - "level": 82 - }, - { - "item": "rs:mahogany_treasure_chest", - "text": "Mahogany treasure chest", - "level": 84 - }, - { - "item": "rs:fancy_jewellery_box", - "text": "Fancy jewellery box", - "level": 86 - }, - { - "item": "rs:mahogany_toy_box", - "text": "Mahogany toy box", - "level": 86 - }, - { - "item": "rs:gilded_mahogany_wardrobe_costume_room", - "text": "Gilded mahogany wardrobe (costume room)", - "level": 87 - }, - { - "item": "rs:gilded_mahogany_wardrobe_bedroom", - "text": "Gilded mahogany wardrobe (Bedroom)", - "level": 87 - }, - { - "item": "rs:marble_cape_rack", - "text": "Marble cape rack", - "level": 90 - }, - { - "item": "rs:marble_wardrobe_costume_room", - "text": "Marble wardrobe (costume room)", - "level": 96 - }, - { - "item": "rs:magic_stone_cape_rack", - "text": "Magic stone cape rack", - "level": 99 - } + { + "name": "Rooms", + "lines": [ + { + "item": "rs:garden", + "text": "Garden", + "level": 1 + }, + { + "item": "rs:parlour", + "text": "Parlour", + "level": 1 + }, + { + "item": "rs:kitchen", + "text": "Kitchen", + "level": 5 + }, + { + "item": "rs:dining_room", + "text": "Dining room", + "level": 10 + }, + { + "item": "rs:workshop", + "text": "Workshop", + "level": 15 + }, + { + "item": "rs:bedroom", + "text": "Bedroom", + "level": 20 + }, + { + "item": "rs:hall_skill_trophies", + "text": "Hall (skill trophies)", + "level": 25 + }, + { + "item": "rs:league_hall", + "text": "Leauge hall", + "level": 27 + }, + { + "item": "rs:games_room", + "text": "Games room", + "level": 30 + }, + { + "item": "rs:combat_room", + "text": "Combat room", + "level": 32 + }, + { + "item": "rs:hall_quest_trophies", + "text": "Hall (quest trophies)", + "level": 35 + }, + { + "item": "rs:menagerie", + "text": "Menagerie", + "level": 37 + }, + { + "item": "rs:study", + "text": "Study", + "level": 40 + }, + { + "item": "rs:costume_room", + "text": "Costume room", + "level": 42 + }, + { + "item": "rs:chapel", + "text": "Chapel", + "level": 45 + }, + { + "item": "rs:portal_chamber", + "text": "Portal chamber", + "level": 50 + }, + { + "item": "rs:formal_garden", + "text": "Formal garden", + "level": 55 + }, + { + "item": "rs:throne_room", + "text": "Throne room", + "level": 60 + }, + { + "item": "rs:oubliette", + "text": "Oubliette", + "level": 65 + }, + { + "item": "rs:superior_garden", + "text": "Superior garden", + "level": 65 + }, + { + "item": "rs:dungeon", + "text": "Dungeon", + "level": 70 + }, + { + "item": "rs:treasure_room", + "text": "Treasure room", + "level": 75 + }, + { + "item": "rs:achievement_gallery", + "text": "Achievement Gallery", + "level": 80 + }, + { + "item": "rs:league_hall", + "text": "Garden", + "level": 1 + } + ] + }, + { + "name": "Skills", + "lines": [ + { + "item": "rs:clay_fireplace", + "text": "Clay fireplace", + "level": 3 + }, + { + "item": "rs:firepit", + "text": "Firepit", + "level": 5 + }, + { + "item": "rs:pump_and_drain", + "text": "Pump and drain", + "level": 7 + }, + { + "item": "rs:firepit_with_hook", + "text": "Firepit with hook", + "level": 11 + }, + { + "item": "rs:repair_bench", + "text": "Repair bench", + "level": 15 + }, + { + "item": "rs:pluming_stand", + "text": "Pluming stand", + "level": 16 + }, + { + "item": "rs:crafting_table_1", + "text": "Crafting table 1", + "level": 16 + }, + { + "item": "rs:firepit_with_pot", + "text": "Firepit with pot", + "level": 17 + }, + { + "item": "rs:wooden_workbench", + "text": "Wooden workbench", + "level": 17 + }, + { + "item": "rs:small_oven", + "text": "Small oven", + "level": 24 + }, + { + "item": "rs:crafting_table_2", + "text": "Crafting table 2", + "level": 25 + }, + { + "item": "rs:pump_and_tub", + "text": "Pump and tub", + "level": 27 + }, + { + "item": "rs:large_oven", + "text": "Large oven", + "level": 29 + }, + { + "item": "rs:oak_workbench", + "text": "Oak workbench", + "level": 32 + }, + { + "item": "rs:stone_fireplace", + "text": "Stone fireplace", + "level": 33 + }, + { + "item": "rs:crafting_table_3", + "text": "Crafting table 3", + "level": 34 + }, + { + "item": "rs:steel_range", + "text": "Steel range", + "level": 34 + }, + { + "item": "rs:whetstone", + "text": "Whetstone", + "level": 35 + }, + { + "item": "rs:shield_easel", + "text": "Shield easel", + "level": 41 + }, + { + "item": "rs:fancy_range", + "text": "Fancy range", + "level": 42 + }, + { + "item": "rs:crafting_table_4", + "text": "Crafting table 4", + "level": 42 + }, + { + "item": "rs:steel_framed_workbench", + "text": "Steel framed workbench", + "level": 46 + }, + { + "item": "rs:sink", + "text": "Sink", + "level": 47 + }, + { + "item": "rs:armour_stand", + "text": "Armour stand", + "level": 55 + }, + { + "item": "rs:workbench_with_vice", + "text": "Workbench with vice", + "level": 62 + }, + { + "item": "rs:marble_fireplace", + "text": "Marble fireplace", + "level": 63 + }, + { + "item": "rs:banner_easel", + "text": "Banner easel", + "level": 66 + }, + { + "item": "rs:workbench_with_lathe", + "text": "Workbench with lathe", + "level": 77 + }, + { + "item": "rs:ancient_altar", + "text": "Ancient altar", + "level": 80 + }, + { + "item": "rs:lunar_altar", + "text": "Lunar altar", + "level": 80 + }, + { + "item": "rs:dark_altar", + "text": "Dark altar", + "level": 80 + } + ] + }, + { + "name": "Surfaces", + "lines": [ + { + "item": "rs:crude_wooden_chair", + "text": "Crude wooden chair", + "level": 1 + }, + { + "item": "rs:wooden_chair", + "text": "Wooden chair", + "level": 8 + }, + { + "item": "rs:wooden_dining_table", + "text": "Wooden dining table", + "level": 10 + }, + { + "item": "rs:wooden_kitchen_table", + "text": "Wooden kitchen table", + "level": 12 + }, + { + "item": "rs:rocking_chair", + "text": "Rocking chair", + "level": 14 + }, + { + "item": "rs:oak_chair", + "text": "Oak chair", + "level": 19 + }, + { + "item": "rs:wooden_bed", + "text": "Wooden bed", + "level": 20 + }, + { + "item": "rs:oak_dining_table", + "text": "Oak dining table", + "level": 22 + }, + { + "item": "rs:oak_dining_bench", + "text": "Oak dining bench", + "level": 22 + }, + { + "item": "rs:oak_armchair", + "text": "Oak armchair", + "level": 26 + }, + { + "item": "rs:oak_bed", + "text": "Oak bed", + "level": 30 + }, + { + "item": "rs:carved_oak_dining_table", + "text": "Carved oak dining table", + "level": 31 + }, + { + "item": "rs:carved_oak_dining_bench", + "text": "Carved oak dining bench", + "level": 31 + }, + { + "item": "rs:oak_kitchen_table", + "text": "Oak kitchen table", + "level": 32 + }, + { + "item": "rs:large_oak_bed", + "text": "Large oak bed", + "level": 34 + }, + { + "item": "rs:teak_armchair", + "text": "Teak armchair", + "level": 35 + }, + { + "item": "rs:teak_dining_table", + "text": "Teak dining table", + "level": 38 + }, + { + "item": "rs:teak_dining_bench", + "text": "Teak dining bench", + "level": 38 + }, + { + "item": "rs:teak_bed", + "text": "Teak bed", + "level": 40 + }, + { + "item": "rs:carved_teak_dining_bench", + "text": "Carved teak dining bench", + "level": 44 + }, + { + "item": "rs:carved_teak_dining_table", + "text": "Carved teak dining table", + "level": 45 + }, + { + "item": "rs:large_teak_bed", + "text": "Large teak bed", + "level": 45 + }, + { + "item": "rs:mahogany_armchair", + "text": "Mahogany armchair", + "level": 50 + }, + { + "item": "rs:mahogany_dining_table", + "text": "Mahogany dining table", + "level": 52 + }, + { + "item": "rs:mahogany_dining_bench", + "text": "Mahogany dining bench", + "level": 52 + }, + { + "item": "rs:teak_kitchen_table", + "text": "Teak kitchen table", + "level": 52 + }, + { + "item": "rs:mahogany_four_poster_bed", + "text": "Mahogany four-poster bed", + "level": 53 + }, + { + "item": "rs:oak_throne", + "text": "Oak throne", + "level": 60 + }, + { + "item": "rs:gilded_mahogany_four_poster_bed", + "text": "Gilded mahogany four-poster bed", + "level": 60 + }, + { + "item": "rs:gilded_mahogany_dining_bench", + "text": "Gilded mahogany dining bench", + "level": 61 + }, + { + "item": "rs:teak_throne", + "text": "Teak throne", + "level": 67 + }, + { + "item": "rs:gilded_mahogany_and_marble_table", + "text": "Gilded mahogany and marble table", + "level": 72 + }, + { + "item": "rs:mahogany_throne", + "text": "Mahogany throne", + "level": 74 + }, + { + "item": "rs:gilded_mahogany_throne", + "text": "Gilded mahogany throne", + "level": 81 + }, + { + "item": "rs:teak_kitchen_table", + "text": "Teak kitchen table", + "level": 52 + }, + { + "item": "rs:teak_kitchen_table", + "text": "Teak kitchen table", + "level": 52 + }, + { + "item": "rs:teak_kitchen_table", + "text": "Teak kitchen table", + "level": 52 + }, + { + "item": "rs:skeleton_throne", + "text": "Skeleton throne", + "level": 88 + }, + { + "item": "rs:crystal_throne", + "text": "Crystal throne", + "level": 95 + }, + { + "item": "rs:demonic_throne", + "text": "Demonic throne", + "level": 99 + } + ] + }, + { + "name": "Storage", + "lines": [ + { + "item": "rs:wooden_bookcase", + "text": "Wooden bookcase", + "level": 4 + }, + { + "item": "rs:wooden_shelves_1", + "text": "Wooden shelves 1", + "level": 6 + }, + { + "item": "rs:beer_barrel", + "text": "Beer barrel", + "level": 7 + }, + { + "item": "rs:wooden_larder", + "text": "Wooden larder", + "level": 9 + }, + { + "item": "rs:cider_barrel", + "text": "Cider barrel", + "level": 12 + }, + { + "item": "rs:wooden_shelves_2", + "text": "Wooden shelves 2", + "level": 12 + }, + { + "item": "rs:tool_store_1", + "text": "Tool store 1", + "level": 15 + }, + { + "item": "rs:asgarnian_ale_barrel", + "text": "Asgarnian ale barrel", + "level": 18 + }, + { + "item": "rs:shoe_box", + "text": "Shoe box", + "level": 20 + }, + { + "item": "rs:wooden_shaving_stand", + "text": "Wooden shaving stand", + "level": 21 + }, + { + "item": "rs:wooden_shelves_3", + "text": "Wooden shelves 3", + "level": 23 + }, + { + "item": "rs:tool_store_2", + "text": "Tool store 2", + "level": 25 + }, + { + "item": "rs:greenmans_ale_barrel", + "text": "Greenman's Ale barrel", + "level": 26 + }, + { + "item": "rs:oak_chest_of_drawers", + "text": "oak chest of drawers", + "level": 27 + }, + { + "item": "rs:oak_bookcase", + "text": "Oak bookcase", + "level": 29 + }, + { + "item": "rs:oak_shaving_stand", + "text": "Oak shaving stand", + "level": 29 + }, + { + "item": "rs:oak_larder", + "text": "Oak larder", + "level": 33 + }, + { + "item": "rs:oak_shelves_1", + "text": "Oak shelves 1", + "level": 34 + }, + { + "item": "rs:tool_store_3", + "text": "Tool store 3", + "level": 35 + }, + { + "item": "rs:dragon_bitter_barrel", + "text": "Dragon Bitter barrel", + "level": 36 + }, + { + "item": "rs:oak_dresser", + "text": "Oak dresser", + "level": 37 + }, + { + "item": "rs:oak_Wardrobe_bedroom", + "text": "Oak wardrobe (bedroom)", + "level": 39 + }, + { + "item": "rs:mahogany_bookcase", + "text": "Mahogany bookcase", + "level": 40 + }, + { + "item": "rs:oak_wardrobe_costume_room", + "text": "Oak wardrobe (costtume room)", + "level": 15 + }, + { + "item": "rs:teak_larder", + "text": "Teak larder", + "level": 43 + }, + { + "item": "rs:oak_fancy_dress_box", + "text": "Oak fancy dress box", + "level": 44 + }, + { + "item": "rs:tool_store_4", + "text": "Tool store 4", + "level": 44 + }, + { + "item": "rs:oak_shelves_2", + "text": "Oak shelves 2", + "level": 45 + }, + { + "item": "rs:oak_armour_case", + "text": "Oak armour case", + "level": 46 + }, + { + "item": "rs:teak_dresser", + "text": "Teak dresser", + "level": 46 + }, + { + "item": "rs:chefs_delight_barrel", + "text": "Chef's Delight barrel", + "level": 48 + }, + { + "item": "rs:oak_treasure_chest", + "text": "Oak treasure chest", + "level": 48 + }, + { + "item": "rs:oak_toy_box", + "text": "Oak toy box", + "level": 50 + }, + { + "item": "rs:carved_oak_wardrobe_costume_room", + "text": "Carved oak wardrobe (costume room)", + "level": 51 + }, + { + "item": "rs:teak_chest_of_drawers", + "text": "Teak chest of drawers", + "level": 51 + }, + { + "item": "rs:oak_cape_rack", + "text": "Oak cape rack", + "level": 54 + }, + { + "item": "rs:tool_store_5", + "text": "Tool store 5", + "level": 55 + }, + { + "item": "rs:teak_shelves_1", + "text": "Teak shelves 1", + "level": 56 + }, + { + "item": "rs:fancy_teak_dresser", + "text": "Fancy teak dresser", + "level": 56 + }, + { + "item": "rs:servants_moneybag", + "text": "Servant's moneybag", + "level": 58 + }, + { + "item": "rs:teak_wardrobe_costume_room", + "text": "Teak wardrobe (costume room)", + "level": 60 + }, + { + "item": "rs:spice_rack", + "text": "Spice Rack", + "level": 60 + }, + { + "item": "rs:teak_fancy_dress_box", + "text": "Teak fancy dress box", + "level": 62 + }, + { + "item": "rs:teak_cape_rack", + "text": "Teak cape rack", + "level": 63 + }, + { + "item": "rs:teak_wardrobe_bedroom", + "text": "Teak wardrobe (bedroom)", + "level": 63 + }, + { + "item": "rs:teak_armour_case", + "text": "Teak armour case", + "level": 64 + }, + { + "item": "rs:mahogany_dresser", + "text": "Mahogany dresser", + "level": 64 + }, + { + "item": "rs:teak_treasure_chest", + "text": "Teak treasure chest", + "level": 66 + }, + { + "item": "rs:teak_toy_box", + "text": "Teak toyo boy", + "level": 68 + }, + { + "item": "rs:carved_teak_wardrobe_costume_room", + "text": "Carved teak wardrobe (costume room)", + "level": 69 + }, + { + "item": "rs:mahogany_cape_rack", + "text": "Mahogany cape rack", + "level": 72 + }, + { + "item": "rs:gilded_mahogany_dresser", + "text": "Gilded mahogany dresser", + "level": 74 + }, + { + "item": "rs:mahogany_wardrobe_bedroom", + "text": "Mahogany wardrobe (bedroom)", + "level": 75 + }, + { + "item": "rs:mahogany_wardrobe_costume_room", + "text": "Mahogany wardrobe (costume room)", + "level": 78 + }, + { + "item": "rs:mahogany_fancy_dress_box", + "text": "Mahogany fancy dress box", + "level": 80 + }, + { + "item": "rs:basic_jewellery_box", + "text": "Basic jewellery box", + "level": 81 + }, + { + "item": "rs:gilded_mahogany_cape_rack", + "text": "Gilded mahogany cape rack", + "level": 81 + }, + { + "item": "rs:mahogany_armour_case", + "text": "Mahogany armour case", + "level": 82 + }, + { + "item": "rs:mahogany_treasure_chest", + "text": "Mahogany treasure chest", + "level": 84 + }, + { + "item": "rs:fancy_jewellery_box", + "text": "Fancy jewellery box", + "level": 86 + }, + { + "item": "rs:mahogany_toy_box", + "text": "Mahogany toy box", + "level": 86 + }, + { + "item": "rs:gilded_mahogany_wardrobe_costume_room", + "text": "Gilded mahogany wardrobe (costume room)", + "level": 87 + }, + { + "item": "rs:gilded_mahogany_wardrobe_bedroom", + "text": "Gilded mahogany wardrobe (Bedroom)", + "level": 87 + }, + { + "item": "rs:marble_cape_rack", + "text": "Marble cape rack", + "level": 90 + }, + { + "item": "rs:marble_wardrobe_costume_room", + "text": "Marble wardrobe (costume room)", + "level": 96 + }, + { + "item": "rs:magic_stone_cape_rack", + "text": "Magic stone cape rack", + "level": 99 + } + ] + }, + { + "name": "Decorative", + "lines": [ + { + "item": "rs:redberry_bushes", + "text": "Redberry bushes\\nPayment: Cabbages(10) x4", + "level": 10 + }, + { + "item": "rs:brown_rug", + "text": "Brown rug", + "level": 2 + }, + { + "item": "rs:torn_curtains", + "text": "Torn curtains", + "level": 2 + }, + { + "item": "rs:rug", + "text": "Rug", + "level": 13 + }, + { + "item": "rs:curtains", + "text": "Curtains", + "level": 18 + }, + { + "item": "rs:oak_clock", + "text": "Oak clock", + "level": 25 + }, + { + "item": "rs:oak_lectern", + "text": "Oak lectern", + "level": 40 + }, + { + "item": "rs:opulent_curtains", + "text": "Opulent curtains", + "level": 40 + }, + { + "item": "rs:globe", + "text": "globe", + "level": 41 + }, + { + "item": "rs:alchemical_chart", + "text": "Alchemical chart", + "level": 43 + }, + { + "item": "rs:wooden_telescope", + "text": "Wooden telescope", + "level": 44 + }, + { + "item": "rs:oak_eagle_lectern", + "text": "Oak eagle lectern", + "level": 47 + }, + { + "item": "rs:oak_demon_lectern", + "text": "Oak demon lectern", + "level": 47 + }, + { + "item": "rs:ornamental_globe", + "text": "Ornamental globe", + "level": 50 + }, + { + "item": "rs:teak_clock", + "text": "Teak clock", + "level": 55 + }, + { + "item": "rs:teak_eagle_lectern", + "text": "Teak eagle lectern", + "level": 57 + }, + { + "item": "rs:teak_demon_lectern", + "text": "Teak demon lectern", + "level": 57 + }, + { + "item": "rs:lunar_globe", + "text": "Lunar globe", + "level": 59 + }, + { + "item": "rs:astronomical_chart", + "text": "Astronomical chart", + "level": 63 + }, + { + "item": "rs:teak_telescope", + "text": "Teak telescope", + "level": 64 + }, + { + "item": "rs:opulent_rug", + "text": "Opulent rug", + "level": 65 + }, + { + "item": "rs:mahogany_eagle_lectern", + "text": "Mahogany eagle lectern", + "level": 67 + }, + { + "item": "rs:mahogany_demon_lectern", + "text": "Mahogany demon lectern", + "level": 67 + }, + { + "item": "rs:celestial_globe", + "text": "Celestial globe", + "level": 68 + }, + { + "item": "rs:dungeon_candles", + "text": "Dungeon candles", + "level": 72 + }, + { + "item": "rs:decorative_dungeon_bloodstain", + "text": "Decorative dungeon bloodstain", + "level": 72 + }, + { + "item": "rs:armillary_sphere", + "text": "Armillary sphere", + "level": 77 + }, + { + "item": "rs:marble_lectern", + "text": "Marble lectern", + "level": 77 + }, + { + "item": "rs:infernal chart", + "text": "Infernal chart", + "level": 83 + }, + { + "item": "rs:decorative_dungeon_pipe", + "text": "Decorative dungeon pipe", + "level": 83 + }, + { + "item": "rs:dungeon_torches", + "text": "Dungeon torches", + "level": 84 + }, + { + "item": "rs:mahoganys_scope", + "text": "Mahogany's scope", + "level": 84 + }, + { + "item": "rs:gilded_mahogany_clock", + "text": "Gilded mahogany clock", + "level": 85 + }, + { + "item": "rs:small_orrery", + "text": "Small orrery", + "level": 86 + }, + { + "item": "rs:hanging_dungeon_skeleton", + "text": "Hanging dungeon skeleton", + "level": 94 + }, + { + "item": "rs:dungeon_skull_torches", + "text": "Dungeon skull torches", + "level": 94 + }, + { + "item": "rs:large_orrery", + "text": "Large orrery", + "level": 95 + } + ] + }, + { + "name": "Trophies", + "lines": [ + { + "item": "rs:oak_wall_decoration", + "text": "Oak wall decoration", + "level": 16 + }, + { + "item": "rs:trophy_pedestal", + "text": "Trophy pedestal", + "level": 27 + }, + { + "item": "rug_league_hall", + "text": "Rug (league hall)", + "level": 28 + }, + { + "item": "rs:trailblazer_rug", + "text": "Trailblazer rug", + "level": 28 + }, + { + "item": "rs:suit_of_armour", + "text": "Suit of armour", + "level": 28 + }, + { + "item": "rs:banner_stand", + "text": "Banner stand", + "level": 30 + }, + { + "item": "rs:league_statue", + "text": "League statue", + "level": 32 + }, + { + "item": "rs:trailblazer_globe", + "text": "Trailblazer globe", + "level": 32 + }, + { + "item": "rs:oak_outfit_stand", + "text": "Oak outfit stand", + "level": 34 + }, + { + "item": "rs:small_potrait", + "text": "Small potrait", + "level": 35 + }, + { + "item": "rs:oak_trophy_case", + "text": "Oak trophy case", + "level": 36 + }, + { + "item": "rs:mounted_bass", + "text": "mounted_bass", + "level": 36 + }, + { + "item": "rs:teak_wall_decoration", + "text": "Teak wall decoration", + "level": 36 + }, + { + "item": "rs:minor_slayer_monster_head", + "text": "Minor Slayer monster head", + "level": 38 + }, + { + "item": "rs:small_map", + "text": "Small map", + "level": 38 + }, + { + "item": "rs:rune_display_cases", + "text": "Rune display cases", + "level": 41 + }, + { + "item": "rs:mounted_sword", + "text": "Mounted sword", + "level": 42 + }, + { + "item": "rs:small_landscape", + "text": "Small landscape", + "level": 44 + }, + { + "item": "rs:mounted_anti_dragon_shield", + "text": "Mounted Anti-Dragon Shield", + "level": 47 + }, + { + "item": "rs:mounted_amulet_of_glory", + "text": "Mounted Amulet of Glory", + "level": 47 + }, + { + "item": "rs:mounted_cape_of_legends", + "text": "Mounted Cape of Legends", + "level": 47 + }, + { + "item": "rs:mounted_mythical_cape", + "text": "Mounted Mythical Cape", + "level": 47 + }, + { + "item": "rs:leagues_accomplishment_scroll", + "text": "Leaugues accomomplishment scroll", + "level": 48 + }, + { + "item": "rs:large_potrait", + "text": "Large potrait", + "level": 55 + }, + { + "item": "rs:gilded_mahogany_wall_decoration", + "text": "Gilded mahogany wall decoration", + "level": 56 + }, + { + "item": "rs:mounted_swordfish", + "text": "Mounted swordfish", + "level": 56 + }, + { + "item": "rs:medium_map", + "text": "Medium map", + "level": 58 + }, + { + "item": "rs:medium_slayer_monster_head", + "text": "Medium Slayer monster head", + "level": 58 + }, + { + "item": "rs:opulent_rug_league_hall", + "text": "Opulent rug league hall", + "level": 65 + }, + { + "item": "rs:large_landscape", + "text": "Large landscape", + "level": 65 + }, + { + "item": "rs:round_wall_mounted_shield", + "text": "Round wall mounted shield", + "level": 66 + }, + { + "item": "rs:mahogany_outfit_stand", + "text": "Mahogany outfit stand", + "level": 74 + }, + { + "item": "rs:mounted_shark", + "text": "Mounted shark", + "level": 76 + }, + { + "item": "rs:square_wall_mounted_shield", + "text": "Square wall-mounted shield", + "level": 76 + }, + { + "item": "rs:mahogany_trophy_case", + "text": "Mahogany trophy case", + "level": 78 + }, + { + "item": "rs:major_slayer_monster_head", + "text": "Major Slayer monster head", + "level": 78 + }, + { + "item": "rs:large_map", + "text": "Large map", + "level": 78 + }, + { + "item": "rs:quest_list", + "text": "Quest list", + "level": 80 + }, + { + "item": "rs:mounted_emblem", + "text": "Mounted emblem", + "level": 80 + }, + { + "item": "rs:mounted_coins", + "text": "Mounted coins", + "level": 80 + }, + { + "item": "rs:cape_hanger", + "text": "Cape hanger", + "level": 80 + }, + { + "item": "rs:mounted_digsite_pendant", + "text": "Mounted Digsite Pendant", + "level": 82 + } + ] + }, + { + "name": "Games", + "lines": [ + { + "item": "rs:hoop_and_stick_game", + "text": "Hoop-and-stick game", + "level": 30 + }, + { + "item": "rs:boxing_ring", + "text": "Boxing ring", + "level": 32 + }, + { + "item": "boxing_glove_rack", + "text": "Boxing glove rack", + "level": 34 + }, + { + "item": "rs:oak_prize_chest", + "text": "Oak pricechest", + "level": 34 + }, + { + "item": "rs:lesser_magical_balance", + "text": "Lesser magical balance", + "level": 37 + }, + { + "item": "rs:jester_game", + "text": "Jester game", + "level": 39 + }, + { + "item": "rs:clay_attack_stone", + "text": "Clay attack stone", + "level": 39 + }, + { + "item": "rs:fencing_ring", + "text": "Fencing ring", + "level": 41 + }, + { + "item": "rs:weapons_rack", + "text": "Weapons rack", + "level": 44 + }, + { + "item": "rs:teak_prize_chest", + "text": "Teak_prize_chest", + "level": 44 + }, + { + "item": "rs:combat_dummy", + "text": "Combat dummy", + "level": 48 + }, + { + "item": "rs:treasure_hunt_fairy_house", + "text": "Treasure hunt fairy house", + "level": 49 + }, + { + "item": "rs:combat_ring", + "text": "Combat ring", + "level": 51 + }, + { + "item": "rs:combat_dummy_undead_and_slayer", + "text": "Combat dummy (Undead and slayer)", + "level": 53 + }, + { + "item": "rs:dartboard", + "text": "Dartboard)", + "level": 54 + }, + { + "item": "rs:extra_weapons_rack", + "text": "Extra weapons rack", + "level": 54 + }, + { + "item": "rs:mahogany_prize_chest", + "text": "Mahogany prize chest", + "level": 54 + }, + { + "item": "rs:medium_balance", + "text": "Medium balance", + "level": 57 + }, + { + "item": "rs:limestone_attack_stone", + "text": "Limestone attack stone", + "level": 59 + }, + { + "item": "rs:hangman_game", + "text": "Hangman game", + "level": 59 + }, + { + "item": "rs:simple_pet_arena", + "text": "Simple pet arena", + "level": 63 + }, + { + "item": "rs:ranging pedestals", + "text": "Ranging pedestals", + "level": 71 + }, + { + "item": "rs:greater_magical_Balance", + "text": "Greater magical balance", + "level": 77 + }, + { + "item": "rs:marble_attack_stone", + "text": "Marble attack stone", + "level": 79 + }, + { + "item": "rs:archery_target", + "text": "Archergy target", + "level": 81 + }, + { + "item": "rs:balance_beam", + "text": "Balance beam", + "level": 81 + } + ] + }, + { + "name": "Garden", + "lines": [ + { + "item": "rs:exit_portal", + "text": "Exit portal", + "level": 1 + }, + { + "item": "rs:low_level_plants", + "text": "Low-level plants", + "level": 1 + }, + { + "item": "rs:decorative_rock", + "text": "Decorative_rock", + "level": 5 + }, + { + "item": "rs:con_tree", + "text": "Tree", + "level": 5 + }, + { + "item": "rs:mid_level_plants", + "text": "Mid-level plants", + "level": 6 + }, + { + "item": "rs:pond", + "text": "Pond", + "level": 10 + }, + { + "item": "rs:nice_tree", + "text": "Nice tree", + "level": 10 + }, + { + "item": "rs:high_level_plants", + "text": "High-level plants", + "level": 12 + }, + { + "item": "rs:imp_statue", + "text": "Imp statue", + "level": 15 + }, + { + "item": "rs:oak_tree", + "text": "Oak tree", + "level": 15 + }, + { + "item": "rs:willow_tree", + "text": "Willow tree", + "level": 30 + }, + { + "item": "rs:tip_jar", + "text": "Tip jar", + "level": 40 + }, + { + "item": "rs:maple_tree", + "text": "Maple tree", + "level": 45 + }, + { + "item": "rs:boundary_stones", + "text": "Boundary stones", + "level": 55 + }, + { + "item": "rs:thorny_hedge", + "text": "Thorny hedge", + "level": 56 + }, + { + "item": "rs:desert_pet_habitat", + "text": "Desert_pet_habitat", + "level": 57 + }, + { + "item": "rs:wooden_fence", + "text": "Wooden fence", + "level": 59 + }, + { + "item": "rs:nice_hedge", + "text": "Nice hedge", + "level": 60 + }, + { + "item": "rs:yew_tree", + "text": "Yew tree", + "level": 60 + }, + { + "item": "rs:stone_wall", + "text": "Stone wall", + "level": 63 + }, + { + "item": "rs:small_box_hedge", + "text": "Small box hedge", + "level": 64 + }, + { + "item": "rs:gazebo", + "text": "Gazebo", + "level": 65 + }, + { + "item": "rs:zen_theme", + "text": "Zen theme", + "level": 65 + }, + { + "item": "rs:topiary_bush", + "text": "Topiary bush", + "level": 65 + }, + { + "item": "rs:sunflower", + "text": "Sunflower", + "level": 66 + }, + { + "item": "rs:rosemary", + "text": "Rosemary", + "level": 66 + }, + { + "item": "rs:teak_garden_bench", + "text": "Teak garden bench", + "level": 66 + }, + { + "item": "rs:iron_railings", + "text": "Iron railings", + "level": 67 + }, + { + "item": "rs:topiary_hedge", + "text": "Topiary hedge", + "level": 68 + }, + { + "item": "rs:dungeon_entrance", + "text": "Dungeon entrance", + "level": 70 + }, + { + "item": "rs:marigolds", + "text": "marigolds", + "level": 71 + }, + { + "item": "rs:daffodils", + "text": "Daffodils", + "level": 71 + }, + { + "item": "rs:picket_fence", + "text": "Picket fence", + "level": 71 + }, + { + "item": "rs:small_fountain", + "text": "Small fountain", + "level": 71 + }, + { + "item": "rs:fancy_hedge", + "text": "Fancy hedge", + "level": 72 + }, + { + "item": "rs:magic_tree", + "text": "Magic tree", + "level": 75 + }, + { + "item": "rs:otherwordly_theme", + "text": "Otherworldly_theme", + "level": 75 + }, + { + "item": "rs:spirit_tree", + "text": "Spirit tree", + "level": 75 + }, + { + "item": "rs:large_fountain", + "text": "Large fountain", + "level": 75 + }, + { + "item": "rs:garden_fence", + "text": "Garden_fence", + "level": 75 + }, + { + "item": "rs:tall_fancy_hedge", + "text": "Tall fancy hedge", + "level": 76 + }, + { + "item": "rs:topiary_bush", + "text": "Topiary bush", + "level": 65 + }, + { + "item": "rs:topiary_bush", + "text": "Topiary bush", + "level": 65 + }, + { + "item": "rs:roses", + "text": "Roses", + "level": 76 + }, + { + "item": "rs:bluebells", + "text": "Bluebells", + "level": 76 + }, + { + "item": "rs:gnome_bench", + "text": "Gnome bench", + "level": 77 + }, + { + "item": "rs:marble_wall", + "text": "Marble wakk", + "level": 79 + }, + { + "item": "rs:obelisk", + "text": "Obelisk", + "level": 80 + }, + { + "item": "rs:tall_box_hedge", + "text": "Tall box hedge", + "level": 80 + }, + { + "item": "rs:posh_fountain", + "text": "Posh fountain", + "level": 81 + }, + { + "item": "rs:fairy_ring", + "text": "Fairy ring", + "level": 85 + }, + { + "item": "rs:marble_garden_bench", + "text": "Marble garden bench (decoration only)", + "level": 88 + } + ] + }, + { + "name": "Dungeon", + "lines": [ + { + "item": "rs:throne_room_floor_decoration", + "text": "2x Throne room floor decoration", + "level": 61 + }, + { + "item": "rs:oak_cage", + "text": "Oak cage", + "level": 65 + }, + { + "item": "rs:oubliette_spikes", + "text": "Oubliette spikes", + "level": 65 + }, + { + "item": "rs:steel_cage", + "text": "Steel cage", + "level": 68 + }, + { + "item": "rs:oak_and_steel_cage", + "text": "Oak and steel cage", + "level": 70 + }, + { + "item": "rs:skeleton_guard", + "text": "Skeleton guard", + "level": 70 + }, + { + "item": "rs:tentacle_pool", + "text": "Tentacle pool", + "level": 71 + }, + { + "item": "rs:spike_trap", + "text": "Spike trap", + "level": 72 + }, + { + "item": "rs:large_trapdoor", + "text": "Large trapdoor", + "level": 74 + }, + { + "item": "rs:oak_dungeon_door", + "text": "Oak dungeon door", + "level": 74 + }, + { + "item": "rs:guard_dog", + "text": "Guard dog", + "level": 74 + }, + { + "item": "rs:wooden_dungeon_treasure_crate", + "text": "Wooden dungeon treasure crate", + "level": 75 + }, + { + "item": "rs:demon", + "text": "Demon", + "level": 75 + }, + { + "item": "rs:steel_cage", + "text": "Steel cage", + "level": 75 + }, + { + "item": "rs:man_trap", + "text": "Man trap", + "level": 76 + }, + { + "item": "rs:oubliette_flame_pit", + "text": "Oubliette flame pit", + "level": 77 + }, + { + "item": "rs:hobgoblin_guard", + "text": "Hobgoblin guard", + "level": 78 + }, + { + "item": "rs:oak_dungeon_treasure_chest", + "text": "Oak dungeon treasure chest", + "level": 79 + }, + { + "item": "rs:spiked_cage", + "text": "Spiked cage", + "level": 80 + }, + { + "item": "rs:tangle_vine", + "text": "Tangle vine", + "level": 80 + }, + { + "item": "rs:Kalphite soldier", + "text": "Kalphite soldier", + "level": 80 + }, + { + "item": "rs:lesser_magic_cage", + "text": "Lesser magic cage", + "level": 82 + }, + { + "item": "rs:baby_red_dragon", + "text": "Baby red dragon", + "level": 82 + }, + { + "item": "rs:teak_dungeon_treasure_chest", + "text": "Teak dungeon treasure chest", + "level": 83 + }, + { + "item": "rs:rocnar", + "text": "Rocnar", + "level": 83 + }, + { + "item": "rs:steel_plated_oak_door", + "text": "Steel plated oak door", + "level": 84 + }, + { + "item": "rs:marble_trap", + "text": "Marble trap", + "level": 84 + }, + { + "item": "rs:tok-xil", + "text": "Tok-Xil", + "level": 85 + }, + { + "item": "rs:bone_cage", + "text": "Bone cage", + "level": 85 + }, + { + "item": "rs:huge_spider", + "text": "Huge spider", + "level": 86 + }, + { + "item": "rs:mahogany_dungeon_treasure_chest", + "text": "Mahogany dungeon treasure chest", + "level": 87 + }, + { + "item": "rs:teleport_trap", + "text": "Teleport trap", + "level": 88 + }, + { + "item": "rs:greater_magic_cage", + "text": "Greater magic cage", + "level": 89 + }, + { + "item": "rs:troll_guard", + "text": "Troll guard", + "level": 90 + }, + { + "item": "rs:dagannoth", + "text": "Dagannoth", + "level": 90 + }, + { + "item": "rs:magic_dungeon_treasure_chest", + "text": "Magic dungeon treasure chest", + "level": 91 + }, + { + "item": "rs:marble_dungeon_door", + "text": "Marble dungeon door", + "level": 94 + }, + { + "item": "rs:hellhound", + "text": "Hellhound", + "level": 94 + }, + { + "item": "rs:steel_dragon", + "text": "steel_dragon", + "level": 95 + } + ] + }, + { + "name": "Chapel", + "lines": [ + { + "item": "rs:oak_altar", + "text": "Oak altar", + "level": 45 + }, + { + "item": "rs:steel_torches_chapel", + "text": "Steel torches chapel", + "level": 45 + }, + { + "item": "rs:icon_of_gnome_child", + "text": "Icon of Gnome Child", + "level": 45 + }, + { + "item": "rs:symbol_of_saradomin", + "text": "Symbol of Saradomin", + "level": 48 + }, + { + "item": "rs:symbol_of_guthix", + "text": "Symbol of Guthix", + "level": 48 + }, + { + "item": "rs:symbol_of_zamorak", + "text": "Symbol of Zamorak", + "level": 48 + }, + { + "item": "rs:wooden_torches_chapel", + "text": "Wooden torches (chapel)", + "level": 48 + }, + { + "item": "rs:chapel_windchimes", + "text": "Chapel windchimes", + "level": 49 + }, + { + "item": "rs:small_chapel_statue", + "text": "Small chapel statue", + "level": 49 + }, + { + "item": "rs:shuttered_chapel_window", + "text": "Shuttered chapel window", + "level": 49 + }, + { + "item": "rs:teak_altar", + "text": "Teak altar", + "level": 50 + }, + { + "item": "rs:steel_candlesticks", + "text": "Steel candlesticks", + "level": 53 + }, + { + "item": "rs:cloth_covered_teak_altar", + "text": "Cloth covered teak altar", + "level": 56 + }, + { + "item": "rs:gold_candlesticks", + "text": "Gold candlesticks", + "level": 57 + }, + { + "item": "rs:chapel_bells", + "text": "Chapel bells", + "level": 58 + }, + { + "item": "rs:icon_of_saradomin", + "text": "Icon of Saradomin", + "level": 59 + }, + { + "item": "rs:Icon of Guthix", + "text": "Icon of Guthix", + "level": 59 + }, + { + "item": "rs:icon_of_zamorak", + "text": "Icon of Zamorak", + "level": 59 + }, + { + "item": "rs:cloth_covered_mahogany_altar", + "text": "Cloth-covered mahogany altar", + "level": 60 + }, + { + "item": "rs:oak_incense_burners", + "text": "Oak incense burners", + "level": 61 + }, + { + "item": "rs:limestone_altar", + "text": "Limestone altar", + "level": 64 + }, + { + "item": "rs:mahogany_incense_burners", + "text": "Mahogany incense burners", + "level": 65 + }, + { + "item": "rs:medium_chapel_statue", + "text": "Medium_chapel_statue", + "level": 69 + }, + { + "item": "rs:chapel_organ", + "text": "Chapel organ", + "level": 69 + }, + { + "item": "rs:decorative_chapel_window", + "text": "Decorative chapel window", + "level": 69 + }, + { + "item": "rs:marble_incense_burner", + "text": "Marble incense burner", + "level": 69 + }, + { + "item": "rs:marble_altar", + "text": "Marble altar", + "level": 70 + }, + { + "item": "rs:icon_of_bob_the_cat", + "text": "Icon of bob the Cat", + "level": 71 + }, + { + "item": "rs:gilded_marble_altar", + "text": "Gilded marble altar", + "level": 75 + }, + { + "item": "rs:large_chapel_statue", + "text": "Large chapel statue", + "level": 89 + }, + { + "item": "rs:stained_glass_chapel_window", + "text": "Stained-glass chapel window", + "level": 89 + } + ] + }, + { + "name": "Other", + "lines": [ + { + "item": "rs:cup_of_tea", + "text": "Mahogany Homes (beginner)", + "level": 1 + }, + { + "item": "rs:cat_blanket", + "text": "Cat blanket", + "level": 5 + }, + { + "item": "rs:stash_units", + "text": "STASH units (beginner)", + "level": 12 + }, + { + "item": "rs:cat_basket", + "text": "Cat basket", + "level": 19 + }, + { + "item": "rs:mahogany_homes", + "text": "Mahogany Homes(novice)", + "level": 20 + }, + { + "item": "rs:rope_bell_pull", + "text": "Rope bell pull", + "level": 26 + }, + { + "item": "rs:oak_staircase", + "text": "Oak staircase", + "level": 27 + }, + { + "item": "rs:stash_units_easy", + "text": "STASH units (easy)", + "level": 27 + }, + { + "item": "rs:cushioned_cat_basket", + "text": "Cushioned cat basket", + "level": 33 + }, + { + "item": "rs:teak_bell_pull", + "text": "Teak bell pull", + "level": 37 + }, + { + "item": "rs:crystal_ball", + "text": "Crystal ball", + "level": 42 + }, + { + "item": "rs:stash_units_medium", + "text": "STASH units (medium)", + "level": 42 + }, + { + "item": "rs:teak_staircase", + "text": "Teak staircase", + "level": 48 + }, + { + "item": "rs:teak_portal_frame", + "text": "Teak portal frame", + "level": 50 + }, + { + "item": "rs:cup_of_tea", + "text": "Mahogany Homes (adept)", + "level": 50 + }, + { + "item": "rs:elemental_sphere", + "text": "Elemental sphere", + "level": 54 + }, + { + "item": "rs:stash_units_hard", + "text": "STASH units (hard)", + "level": 50 + }, + { + "item": "rs:hallowed_sepulchre", + "text": "Hallowed Sepulchre - Repair bridge", + "level": 56 + }, + { + "item": "rs:gilded_teak_bell_pull", + "text": "Gilded teak bell pull", + "level": 60 + }, + { + "item": "rs:greater_teleport_focus", + "text": "Greater teleport focus", + "level": 65 + }, + { + "item": "rs:mahogany_portal_frame", + "text": "Mahogany portal frame", + "level": 65 + }, + { + "item": "rs:crystal_of_power", + "text": "Crystal of power", + "level": 66 + }, + { + "item": "rs:limestone_spiral_staircase", + "text": "Limestone spiral staircase", + "level": 67 + }, + { + "item": "rs:oak_oubliette_ladrer", + "text": "Oak oubliette ladder", + "level": 68 + }, + { + "item": "rs:oak_lever", + "text": "Oak lever", + "level": 68 + }, + { + "item": "rs:stash_units_elite", + "text": "STASH units (Elite)", + "level": 77 + }, + { + "item": "rs:teak_oubliette_ladder", + "text": "Teak oubliette ladder", + "level": 78 + }, + { + "item": "rs:teak_lever", + "text": "Teak lever", + "level": 78 + }, + { + "item": "rs:marble_portal_frame", + "text": "Marble portal frame", + "level": 80 + }, + { + "item": "rs:scrying_pool", + "text": "Scrying pool", + "level": 80 + }, + { + "item": "rs:marble_staircase", + "text": "Marble staircase", + "level": 82 + }, + { + "item": "rs:mahogany_oubliette_ladder", + "text": "Mahogany oubliette ladder", + "level": 88 + }, + { + "item": "rs:mahogany_lever", + "text": "Mahogany lever", + "level": 88 + }, + { + "item": "rs:stash_units_master", + "text": "STASH units (master)", + "level": 88 + }, + { + "item": "rs:marble_spiral", + "text": "Marble spiral", + "level": 97 + } + ] + }, + { + "name": "Servants", + "lines": [ + { + "item": "rs:servant_rick", + "text": "Rick", + "level": 20 + }, + { + "item": "rs:servant_maid", + "text": "Maid", + "level": 25 + }, + { + "item": "rs:servant_cook", + "text": "Cook", + "level": 30 + }, + { + "item": "rs:servant_butler", + "text": "Butler", + "level": 39 + }, + { + "item": "rs:servant_demon_butler", + "text": "Demon Butler", + "level": 50 + } + ] + }, + { + "name": "House Size", + "lines": [ + { + "item": "rs:hammer", + "text": "Maximum rooms: 24", + "level": 1 + }, + { + "item": "rs:saw", + "text": "Maximum dimensions: 3x3", + "level": 1 + }, + { + "item": "rs:saw", + "text": "Maximum dimensions: 4x4", + "level": 15 + }, + { + "item": "rs:saw", + "text": "Maximum dimensions: 5x5", + "level": 30 + }, + { + "item": "rs:saw", + "text": "Maximum dimensions: 6x6", + "level": 45 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 25", + "level": 50 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 26", + "level": 56 + }, + { + "item": "rs:saw", + "text": "Maximum dimensions: 7x7", + "level": 60 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 27", + "level": 62 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 28", + "level": 68 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 29", + "level": 74 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 30", + "level": 80 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 31", + "level": 86 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 32", + "level": 92 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 33", + "level": 96 + }, + { + "item": "rs:hammer", + "text": "Maximum rooms: 34", + "level": 99 + } + ] + } ] - },{ - "name": "Decorative", - "lines": [ - { - "item": "rs:redberry_bushes", - "text": "Redberry bushes\\nPayment: Cabbages(10) x4", - "level": 10 - }, - { - "item": "rs:brown_rug", - "text": "Brown rug", - "level": 2 - }, - { - "item": "rs:torn_curtains", - "text": "Torn curtains", - "level": 2 - }, - { - "item": "rs:rug", - "text": "Rug", - "level": 13 - }, - { - "item": "rs:curtains", - "text": "Curtains", - "level": 18 - }, - { - "item": "rs:oak_clock", - "text": "Oak clock", - "level": 25 - }, - { - "item": "rs:oak_lectern", - "text": "Oak lectern", - "level": 40 - }, - { - "item": "rs:opulent_curtains", - "text": "Opulent curtains", - "level": 40 - }, - { - "item": "rs:globe", - "text": "globe", - "level": 41 - }, - { - "item": "rs:alchemical_chart", - "text": "Alchemical chart", - "level": 43 - }, - { - "item": "rs:wooden_telescope", - "text": "Wooden telescope", - "level": 44 - }, - { - "item": "rs:oak_eagle_lectern", - "text": "Oak eagle lectern", - "level": 47 - }, - { - "item": "rs:oak_demon_lectern", - "text": "Oak demon lectern", - "level": 47 - }, - { - "item": "rs:ornamental_globe", - "text": "Ornamental globe", - "level": 50 - }, - { - "item": "rs:teak_clock", - "text": "Teak clock", - "level": 55 - }, - { - "item": "rs:teak_eagle_lectern", - "text": "Teak eagle lectern", - "level": 57 - }, - { - "item": "rs:teak_demon_lectern", - "text": "Teak demon lectern", - "level": 57 - }, - { - "item": "rs:lunar_globe", - "text": "Lunar globe", - "level": 59 - }, - { - "item": "rs:astronomical_chart", - "text": "Astronomical chart", - "level": 63 - }, - { - "item": "rs:teak_telescope", - "text": "Teak telescope", - "level": 64 - }, - { - "item": "rs:opulent_rug", - "text": "Opulent rug", - "level": 65 - }, - { - "item": "rs:mahogany_eagle_lectern", - "text": "Mahogany eagle lectern", - "level": 67 - }, - { - "item": "rs:mahogany_demon_lectern", - "text": "Mahogany demon lectern", - "level": 67 - }, - { - "item": "rs:celestial_globe", - "text": "Celestial globe", - "level": 68 - }, - { - "item": "rs:dungeon_candles", - "text": "Dungeon candles", - "level": 72 - }, - { - "item": "rs:decorative_dungeon_bloodstain", - "text": "Decorative dungeon bloodstain", - "level": 72 - }, - { - "item": "rs:armillary_sphere", - "text": "Armillary sphere", - "level": 77 - }, - { - "item": "rs:marble_lectern", - "text": "Marble lectern", - "level": 77 - }, - { - "item": "rs:infernal chart", - "text": "Infernal chart", - "level": 83 - }, - { - "item": "rs:decorative_dungeon_pipe", - "text": "Decorative dungeon pipe", - "level": 83 - }, - { - "item": "rs:dungeon_torches", - "text": "Dungeon torches", - "level": 84 - }, - { - "item": "rs:mahoganys_scope", - "text": "Mahogany's scope", - "level": 84 - }, - { - "item": "rs:gilded_mahogany_clock", - "text": "Gilded mahogany clock", - "level": 85 - }, - { - "item": "rs:small_orrery", - "text": "Small orrery", - "level": 86 - }, - { - "item": "rs:hanging_dungeon_skeleton", - "text": "Hanging dungeon skeleton", - "level": 94 - }, - { - "item": "rs:dungeon_skull_torches", - "text": "Dungeon skull torches", - "level": 94 - }, - { - "item": "rs:large_orrery", - "text": "Large orrery", - "level": 95 - } - ] - },{ - "name": "Trophies", - "lines": [ - { - "item": "rs:oak_wall_decoration", - "text": "Oak wall decoration", - "level": 16 - }, - { - "item": "rs:trophy_pedestal", - "text": "Trophy pedestal", - "level": 27 - }, - { - "item": "rug_league_hall", - "text": "Rug (league hall)", - "level": 28 - }, - { - "item": "rs:trailblazer_rug", - "text": "Trailblazer rug", - "level": 28 - }, - { - "item": "rs:suit_of_armour", - "text": "Suit of armour", - "level": 28 - }, - { - "item": "rs:banner_stand", - "text": "Banner stand", - "level": 30 - }, - { - "item": "rs:league_statue", - "text": "League statue", - "level": 32 - }, - { - "item": "rs:trailblazer_globe", - "text": "Trailblazer globe", - "level": 32 - }, - { - "item": "rs:oak_outfit_stand", - "text": "Oak outfit stand", - "level": 34 - }, - { - "item": "rs:small_potrait", - "text": "Small potrait", - "level": 35 - }, - { - "item": "rs:oak_trophy_case", - "text": "Oak trophy case", - "level": 36 - }, - { - "item": "rs:mounted_bass", - "text": "mounted_bass", - "level": 36 - }, - { - "item": "rs:teak_wall_decoration", - "text": "Teak wall decoration", - "level": 36 - }, - { - "item": "rs:minor_slayer_monster_head", - "text": "Minor Slayer monster head", - "level": 38 - }, - { - "item": "rs:small_map", - "text": "Small map", - "level": 38 - }, - { - "item": "rs:rune_display_cases", - "text": "Rune display cases", - "level": 41 - }, - { - "item": "rs:mounted_sword", - "text": "Mounted sword", - "level": 42 - }, - { - "item": "rs:small_landscape", - "text": "Small landscape", - "level": 44 - }, - { - "item": "rs:mounted_anti_dragon_shield", - "text": "Mounted Anti-Dragon Shield", - "level": 47 - }, - { - "item": "rs:mounted_amulet_of_glory", - "text": "Mounted Amulet of Glory", - "level": 47 - }, - { - "item": "rs:mounted_cape_of_legends", - "text": "Mounted Cape of Legends", - "level": 47 - }, - { - "item": "rs:mounted_mythical_cape", - "text": "Mounted Mythical Cape", - "level": 47 - }, - { - "item": "rs:leagues_accomplishment_scroll", - "text": "Leaugues accomomplishment scroll", - "level": 48 - }, - { - "item": "rs:large_potrait", - "text": "Large potrait", - "level": 55 - }, - { - "item": "rs:gilded_mahogany_wall_decoration", - "text": "Gilded mahogany wall decoration", - "level": 56 - }, - { - "item": "rs:mounted_swordfish", - "text": "Mounted swordfish", - "level": 56 - }, - { - "item": "rs:medium_map", - "text": "Medium map", - "level": 58 - }, - { - "item": "rs:medium_slayer_monster_head", - "text": "Medium Slayer monster head", - "level": 58 - }, - { - "item": "rs:opulent_rug_league_hall", - "text": "Opulent rug league hall", - "level": 65 - }, - { - "item": "rs:large_landscape", - "text": "Large landscape", - "level": 65 - }, - { - "item": "rs:round_wall_mounted_shield", - "text": "Round wall mounted shield", - "level": 66 - }, - { - "item": "rs:mahogany_outfit_stand", - "text": "Mahogany outfit stand", - "level": 74 - }, - { - "item": "rs:mounted_shark", - "text": "Mounted shark", - "level": 76 - }, - { - "item": "rs:square_wall_mounted_shield", - "text": "Square wall-mounted shield", - "level": 76 - }, - { - "item": "rs:mahogany_trophy_case", - "text": "Mahogany trophy case", - "level": 78 - }, - { - "item": "rs:major_slayer_monster_head", - "text": "Major Slayer monster head", - "level": 78 - }, - { - "item": "rs:large_map", - "text": "Large map", - "level": 78 - }, - { - "item": "rs:quest_list", - "text": "Quest list", - "level": 80 - }, - { - "item": "rs:mounted_emblem", - "text": "Mounted emblem", - "level": 80 - }, - { - "item": "rs:mounted_coins", - "text": "Mounted coins", - "level": 80 - }, - { - "item": "rs:cape_hanger", - "text": "Cape hanger", - "level": 80 - }, - { - "item": "rs:mounted_digsite_pendant", - "text": "Mounted Digsite Pendant", - "level": 82 - } - ] - },{ - "name": "Games", - "lines": [ - { - "item": "rs:hoop_and_stick_game", - "text": "Hoop-and-stick game", - "level": 30 - }, - { - "item": "rs:boxing_ring", - "text": "Boxing ring", - "level": 32 - }, - { - "item": "boxing_glove_rack", - "text": "Boxing glove rack", - "level": 34 - }, - { - "item": "rs:oak_prize_chest", - "text": "Oak pricechest", - "level": 34 - }, - { - "item": "rs:lesser_magical_balance", - "text": "Lesser magical balance", - "level": 37 - }, - { - "item": "rs:jester_game", - "text": "Jester game", - "level": 39 - }, - { - "item": "rs:clay_attack_stone", - "text": "Clay attack stone", - "level": 39 - }, - { - "item": "rs:fencing_ring", - "text": "Fencing ring", - "level": 41 - }, - { - "item": "rs:weapons_rack", - "text": "Weapons rack", - "level": 44 - }, - { - "item": "rs:teak_prize_chest", - "text": "Teak_prize_chest", - "level": 44 - }, - { - "item": "rs:combat_dummy", - "text": "Combat dummy", - "level": 48 - }, - { - "item": "rs:treasure_hunt_fairy_house", - "text": "Treasure hunt fairy house", - "level": 49 - }, - { - "item": "rs:combat_ring", - "text": "Combat ring", - "level": 51 - }, - { - "item": "rs:combat_dummy_undead_and_slayer", - "text": "Combat dummy (Undead and slayer)", - "level": 53 - }, - { - "item": "rs:dartboard", - "text": "Dartboard)", - "level": 54 - }, - { - "item": "rs:extra_weapons_rack", - "text": "Extra weapons rack", - "level": 54 - }, - { - "item": "rs:mahogany_prize_chest", - "text": "Mahogany prize chest", - "level": 54 - }, - { - "item": "rs:medium_balance", - "text": "Medium balance", - "level": 57 - }, - { - "item": "rs:limestone_attack_stone", - "text": "Limestone attack stone", - "level": 59 - }, - { - "item": "rs:hangman_game", - "text": "Hangman game", - "level": 59 - }, - { - "item": "rs:simple_pet_arena", - "text": "Simple pet arena", - "level": 63 - }, - { - "item": "rs:ranging pedestals", - "text": "Ranging pedestals", - "level": 71 - }, - { - "item": "rs:greater_magical_Balance", - "text": "Greater magical balance", - "level": 77 - }, - { - "item": "rs:marble_attack_stone", - "text": "Marble attack stone", - "level": 79 - }, - { - "item": "rs:archery_target", - "text": "Archergy target", - "level": 81 - }, - { - "item": "rs:balance_beam", - "text": "Balance beam", - "level": 81 - } - ] - },{ - "name": "Garden", - "lines": [ - { - "item": "rs:exit_portal", - "text": "Exit portal", - "level": 1 - }, - { - "item": "rs:low_level_plants", - "text": "Low-level plants", - "level": 1 - }, - { - "item": "rs:decorative_rock", - "text": "Decorative_rock", - "level": 5 - }, - { - "item": "rs:con_tree", - "text": "Tree", - "level": 5 - }, - { - "item": "rs:mid_level_plants", - "text": "Mid-level plants", - "level": 6 - }, { - "item": "rs:pond", - "text": "Pond", - "level": 10 - }, - { - "item": "rs:nice_tree", - "text": "Nice tree", - "level": 10 - }, - { - "item": "rs:high_level_plants", - "text": "High-level plants", - "level": 12 - }, - { - "item": "rs:imp_statue", - "text": "Imp statue", - "level": 15 - }, - { - "item": "rs:oak_tree", - "text": "Oak tree", - "level": 15 - }, - { - "item": "rs:willow_tree", - "text": "Willow tree", - "level": 30 - }, - { - "item": "rs:tip_jar", - "text": "Tip jar", - "level": 40 - }, - { - "item": "rs:maple_tree", - "text": "Maple tree", - "level": 45 - }, - { - "item": "rs:boundary_stones", - "text": "Boundary stones", - "level": 55 - }, - { - "item": "rs:thorny_hedge", - "text": "Thorny hedge", - "level": 56 - }, - { - "item": "rs:desert_pet_habitat", - "text": "Desert_pet_habitat", - "level": 57 - }, - { - "item": "rs:wooden_fence", - "text": "Wooden fence", - "level": 59 - }, - { - "item": "rs:nice_hedge", - "text": "Nice hedge", - "level": 60 - }, - { - "item": "rs:yew_tree", - "text": "Yew tree", - "level": 60 - }, - { - "item": "rs:stone_wall", - "text": "Stone wall", - "level": 63 - }, - { - "item": "rs:small_box_hedge", - "text": "Small box hedge", - "level": 64 - }, - { - "item": "rs:gazebo", - "text": "Gazebo", - "level": 65 - }, - { - "item": "rs:zen_theme", - "text": "Zen theme", - "level": 65 - }, - { - "item": "rs:topiary_bush", - "text": "Topiary bush", - "level": 65 - }, - { - "item": "rs:sunflower", - "text": "Sunflower", - "level": 66 - }, - { - "item": "rs:rosemary", - "text": "Rosemary", - "level": 66 - }, - { - "item": "rs:teak_garden_bench", - "text": "Teak garden bench", - "level": 66 - }, - { - "item": "rs:iron_railings", - "text": "Iron railings", - "level": 67 - }, - { - "item": "rs:topiary_hedge", - "text": "Topiary hedge", - "level": 68 - }, - { - "item": "rs:dungeon_entrance", - "text": "Dungeon entrance", - "level": 70 - }, - { - "item": "rs:marigolds", - "text": "marigolds", - "level": 71 - }, - { - "item": "rs:daffodils", - "text": "Daffodils", - "level": 71 - }, - { - "item": "rs:picket_fence", - "text": "Picket fence", - "level": 71 - }, - { - "item": "rs:small_fountain", - "text": "Small fountain", - "level": 71 - }, - { - "item": "rs:fancy_hedge", - "text": "Fancy hedge", - "level": 72 - }, - { - "item": "rs:magic_tree", - "text": "Magic tree", - "level": 75 - }, - { - "item": "rs:otherwordly_theme", - "text": "Otherworldly_theme", - "level": 75 - }, - { - "item": "rs:spirit_tree", - "text": "Spirit tree", - "level": 75 - }, - { - "item": "rs:large_fountain", - "text": "Large fountain", - "level": 75 - }, - { - "item": "rs:garden_fence", - "text": "Garden_fence", - "level": 75 - }, - { - "item": "rs:tall_fancy_hedge", - "text": "Tall fancy hedge", - "level": 76 - }, - { - "item": "rs:topiary_bush", - "text": "Topiary bush", - "level": 65 - }, - { - "item": "rs:topiary_bush", - "text": "Topiary bush", - "level": 65 - }, - { - "item": "rs:roses", - "text": "Roses", - "level": 76 - }, - { - "item": "rs:bluebells", - "text": "Bluebells", - "level": 76 - }, - { - "item": "rs:gnome_bench", - "text": "Gnome bench", - "level": 77 - }, - { - "item": "rs:marble_wall", - "text": "Marble wakk", - "level": 79 - }, - { - "item": "rs:obelisk", - "text": "Obelisk", - "level": 80 - }, - { - "item": "rs:tall_box_hedge", - "text": "Tall box hedge", - "level": 80 - }, - { - "item": "rs:posh_fountain", - "text": "Posh fountain", - "level": 81 - }, - { - "item": "rs:fairy_ring", - "text": "Fairy ring", - "level": 85 - }, - { - "item": "rs:marble_garden_bench", - "text": "Marble garden bench (decoration only)", - "level": 88 - } - ] - },{ - "name": "Dungeon", - "lines": [ - { - "item": "rs:throne_room_floor_decoration", - "text": "2x Throne room floor decoration", - "level": 61 - }, - { - "item": "rs:oak_cage", - "text": "Oak cage", - "level": 65 - }, - { - "item": "rs:oubliette_spikes", - "text": "Oubliette spikes", - "level": 65 - }, - { - "item": "rs:steel_cage", - "text": "Steel cage", - "level": 68 - }, - { - "item": "rs:oak_and_steel_cage", - "text": "Oak and steel cage", - "level": 70 - }, { - "item": "rs:skeleton_guard", - "text": "Skeleton guard", - "level": 70 - }, - { - "item": "rs:tentacle_pool", - "text": "Tentacle pool", - "level": 71 - }, - { - "item": "rs:spike_trap", - "text": "Spike trap", - "level": 72 - }, - { - "item": "rs:large_trapdoor", - "text": "Large trapdoor", - "level": 74 - }, - { - "item": "rs:oak_dungeon_door", - "text": "Oak dungeon door", - "level": 74 - }, - { - "item": "rs:guard_dog", - "text": "Guard dog", - "level": 74 - }, - { - "item": "rs:wooden_dungeon_treasure_crate", - "text": "Wooden dungeon treasure crate", - "level": 75 - }, - { - "item": "rs:demon", - "text": "Demon", - "level": 75 - }, - { - "item": "rs:steel_cage", - "text": "Steel cage", - "level": 75 - }, - { - "item": "rs:man_trap", - "text": "Man trap", - "level": 76 - }, - { - "item": "rs:oubliette_flame_pit", - "text": "Oubliette flame pit", - "level": 77 - }, - { - "item": "rs:hobgoblin_guard", - "text": "Hobgoblin guard", - "level": 78 - }, - { - "item": "rs:oak_dungeon_treasure_chest", - "text": "Oak dungeon treasure chest", - "level": 79 - }, - { - "item": "rs:spiked_cage", - "text": "Spiked cage", - "level": 80 - }, - { - "item": "rs:tangle_vine", - "text": "Tangle vine", - "level": 80 - }, - { - "item": "rs:Kalphite soldier", - "text": "Kalphite soldier", - "level": 80 - }, - { - "item": "rs:lesser_magic_cage", - "text": "Lesser magic cage", - "level": 82 - }, - { - "item": "rs:baby_red_dragon", - "text": "Baby red dragon", - "level": 82 - }, - { - "item": "rs:teak_dungeon_treasure_chest", - "text": "Teak dungeon treasure chest", - "level": 83 - }, - { - "item": "rs:rocnar", - "text": "Rocnar", - "level": 83 - }, - { - "item": "rs:steel_plated_oak_door", - "text": "Steel plated oak door", - "level": 84 - }, - { - "item": "rs:marble_trap", - "text": "Marble trap", - "level": 84 - }, - { - "item": "rs:tok-xil", - "text": "Tok-Xil", - "level": 85 - }, - { - "item": "rs:bone_cage", - "text": "Bone cage", - "level": 85 - }, - { - "item": "rs:huge_spider", - "text": "Huge spider", - "level": 86 - }, - { - "item": "rs:mahogany_dungeon_treasure_chest", - "text": "Mahogany dungeon treasure chest", - "level": 87 - }, - { - "item": "rs:teleport_trap", - "text": "Teleport trap", - "level": 88 - }, - { - "item": "rs:greater_magic_cage", - "text": "Greater magic cage", - "level": 89 - }, - { - "item": "rs:troll_guard", - "text": "Troll guard", - "level": 90 - }, - { - "item": "rs:dagannoth", - "text": "Dagannoth", - "level": 90 - }, - { - "item": "rs:magic_dungeon_treasure_chest", - "text": "Magic dungeon treasure chest", - "level": 91 - }, - { - "item": "rs:marble_dungeon_door", - "text": "Marble dungeon door", - "level": 94 - }, - { - "item": "rs:hellhound", - "text": "Hellhound", - "level": 94 - }, - { - "item": "rs:steel_dragon", - "text": "steel_dragon", - "level": 95 - } - ] - },{ - "name": "Chapel", - "lines": [ - { - "item": "rs:oak_altar", - "text": "Oak altar", - "level": 45 - }, - { - "item": "rs:steel_torches_chapel", - "text": "Steel torches chapel", - "level": 45 - }, - { - "item": "rs:icon_of_gnome_child", - "text": "Icon of Gnome Child", - "level": 45 - }, - { - "item": "rs:symbol_of_saradomin", - "text": "Symbol of Saradomin", - "level": 48 - }, - { - "item": "rs:symbol_of_guthix", - "text": "Symbol of Guthix", - "level": 48 - }, { - "item": "rs:symbol_of_zamorak", - "text": "Symbol of Zamorak", - "level": 48 - }, - { - "item": "rs:wooden_torches_chapel", - "text": "Wooden torches (chapel)", - "level": 48 - }, - { - "item": "rs:chapel_windchimes", - "text": "Chapel windchimes", - "level": 49 - }, - { - "item": "rs:small_chapel_statue", - "text": "Small chapel statue", - "level": 49 - }, - { - "item": "rs:shuttered_chapel_window", - "text": "Shuttered chapel window", - "level": 49 - }, - { - "item": "rs:teak_altar", - "text": "Teak altar", - "level": 50 - }, - { - "item": "rs:steel_candlesticks", - "text": "Steel candlesticks", - "level": 53 - }, - { - "item": "rs:cloth_covered_teak_altar", - "text": "Cloth covered teak altar", - "level": 56 - }, - { - "item": "rs:gold_candlesticks", - "text": "Gold candlesticks", - "level": 57 - }, - { - "item": "rs:chapel_bells", - "text": "Chapel bells", - "level": 58 - }, - { - "item": "rs:icon_of_saradomin", - "text": "Icon of Saradomin", - "level": 59 - }, - { - "item": "rs:Icon of Guthix", - "text": "Icon of Guthix", - "level": 59 - }, - { - "item": "rs:icon_of_zamorak", - "text": "Icon of Zamorak", - "level": 59 - }, - { - "item": "rs:cloth_covered_mahogany_altar", - "text": "Cloth-covered mahogany altar", - "level": 60 - }, - { - "item": "rs:oak_incense_burners", - "text": "Oak incense burners", - "level": 61 - }, - { - "item": "rs:limestone_altar", - "text": "Limestone altar", - "level": 64 - }, - { - "item": "rs:mahogany_incense_burners", - "text": "Mahogany incense burners", - "level": 65 - }, - { - "item": "rs:medium_chapel_statue", - "text": "Medium_chapel_statue", - "level": 69 - }, - { - "item": "rs:chapel_organ", - "text": "Chapel organ", - "level": 69 - }, - { - "item": "rs:decorative_chapel_window", - "text": "Decorative chapel window", - "level": 69 - }, - { - "item": "rs:marble_incense_burner", - "text": "Marble incense burner", - "level": 69 - }, - { - "item": "rs:marble_altar", - "text": "Marble altar", - "level": 70 - }, - { - "item": "rs:icon_of_bob_the_cat", - "text": "Icon of bob the Cat", - "level": 71 - }, - { - "item": "rs:gilded_marble_altar", - "text": "Gilded marble altar", - "level": 75 - }, - { - "item": "rs:large_chapel_statue", - "text": "Large chapel statue", - "level": 89 - }, - { - "item": "rs:stained_glass_chapel_window", - "text": "Stained-glass chapel window", - "level": 89 - } - ] - },{ - "name": "Other", - "lines": [ - { - "item": "rs:cup_of_tea", - "text": "Mahogany Homes (beginner)", - "level": 1 - }, - { - "item": "rs:cat_blanket", - "text": "Cat blanket", - "level": 5 - }, - { - "item": "rs:stash_units", - "text": "STASH units (beginner)", - "level": 12 - }, - { - "item": "rs:cat_basket", - "text": "Cat basket", - "level": 19 - }, - { - "item": "rs:mahogany_homes", - "text": "Mahogany Homes(novice)", - "level": 20 - }, { - "item": "rs:rope_bell_pull", - "text": "Rope bell pull", - "level": 26 - }, - { - "item": "rs:oak_staircase", - "text": "Oak staircase", - "level": 27 - }, - { - "item": "rs:stash_units_easy", - "text": "STASH units (easy)", - "level": 27 - }, - { - "item": "rs:cushioned_cat_basket", - "text": "Cushioned cat basket", - "level": 33 - }, - { - "item": "rs:teak_bell_pull", - "text": "Teak bell pull", - "level": 37 - }, - { - "item": "rs:crystal_ball", - "text": "Crystal ball", - "level": 42 - }, - { - "item": "rs:stash_units_medium", - "text": "STASH units (medium)", - "level": 42 - }, - { - "item": "rs:teak_staircase", - "text": "Teak staircase", - "level": 48 - }, - { - "item": "rs:teak_portal_frame", - "text": "Teak portal frame", - "level": 50 - }, - { - "item": "rs:cup_of_tea", - "text": "Mahogany Homes (adept)", - "level": 50 - }, - { - "item": "rs:elemental_sphere", - "text": "Elemental sphere", - "level": 54 - }, - { - "item": "rs:stash_units_hard", - "text": "STASH units (hard)", - "level": 50 - }, - { - "item": "rs:hallowed_sepulchre", - "text": "Hallowed Sepulchre - Repair bridge", - "level": 56 - }, - { - "item": "rs:gilded_teak_bell_pull", - "text": "Gilded teak bell pull", - "level": 60 - }, - { - "item": "rs:greater_teleport_focus", - "text": "Greater teleport focus", - "level": 65 - }, - { - "item": "rs:mahogany_portal_frame", - "text": "Mahogany portal frame", - "level": 65 - }, - { - "item": "rs:crystal_of_power", - "text": "Crystal of power", - "level": 66 - }, - { - "item": "rs:limestone_spiral_staircase", - "text": "Limestone spiral staircase", - "level": 67 - }, - { - "item": "rs:oak_oubliette_ladrer", - "text": "Oak oubliette ladder", - "level": 68 - }, - { - "item": "rs:oak_lever", - "text": "Oak lever", - "level": 68 - }, - { - "item": "rs:stash_units_elite", - "text": "STASH units (Elite)", - "level": 77 - }, - { - "item": "rs:teak_oubliette_ladder", - "text": "Teak oubliette ladder", - "level": 78 - }, - { - "item": "rs:teak_lever", - "text": "Teak lever", - "level": 78 - }, - { - "item": "rs:marble_portal_frame", - "text": "Marble portal frame", - "level": 80 - }, - { - "item": "rs:scrying_pool", - "text": "Scrying pool", - "level": 80 - }, - { - "item": "rs:marble_staircase", - "text": "Marble staircase", - "level": 82 - }, - { - "item": "rs:mahogany_oubliette_ladder", - "text": "Mahogany oubliette ladder", - "level": 88 - }, - { - "item": "rs:mahogany_lever", - "text": "Mahogany lever", - "level": 88 - }, - { - "item": "rs:stash_units_master", - "text": "STASH units (master)", - "level": 88 - }, - { - "item": "rs:marble_spiral", - "text": "Marble spiral", - "level": 97 - } - ] - },{ - "name": "Servants", - "lines": [ - { - "item": "rs:servant_rick", - "text": "Rick", - "level": 20 - }, - { - "item": "rs:servant_maid", - "text": "Maid", - "level": 25 - }, - { - "item": "rs:servant_cook", - "text": "Cook", - "level": 30 - }, - { - "item": "rs:servant_butler", - "text": "Butler", - "level": 39 - }, - { - "item": "rs:servant_demon_butler", - "text": "Demon Butler", - "level": 50 - } - ] - },{ - "name": "House Size", - "lines": [ - { - "item": "rs:hammer", - "text": "Maximum rooms: 24", - "level": 1 - }, - { - "item": "rs:saw", - "text": "Maximum dimensions: 3x3", - "level": 1 - }, - { - "item": "rs:saw", - "text": "Maximum dimensions: 4x4", - "level": 15 - }, - { - "item": "rs:saw", - "text": "Maximum dimensions: 5x5", - "level": 30 - }, - { - "item": "rs:saw", - "text": "Maximum dimensions: 6x6", - "level": 45 - }, { - "item": "rs:hammer", - "text": "Maximum rooms: 25", - "level": 50 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 26", - "level": 56 - }, - { - "item": "rs:saw", - "text": "Maximum dimensions: 7x7", - "level": 60 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 27", - "level": 62 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 28", - "level": 68 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 29", - "level": 74 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 30", - "level": 80 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 31", - "level": 86 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 32", - "level": 92 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 33", - "level": 96 - }, - { - "item": "rs:hammer", - "text": "Maximum rooms: 34", - "level": 99 - } - ] - } -] } diff --git a/src/plugins/skills/skill-guides/cooking.json b/src/plugins/skills/skill-guides/cooking.json index 6c3d5169c..8a5270ba0 100644 --- a/src/plugins/skills/skill-guides/cooking.json +++ b/src/plugins/skills/skill-guides/cooking.json @@ -1,442 +1,442 @@ { - "id": 129, - "name": "Cooking", - "members": false, - "sub_guides": [ - { - "name": "Meats", - "lines": [ - { - "item": "rs:meat", - "text": "Meat", - "level": 1 - }, - { - "item": "rs:shrimps", - "text": "Shrimp", - "level": 1 - }, - { - "item": "rs:chicken", - "text": "Chicken", - "level": 1 - }, - { - "item": "rs:anchovies", - "text": "Anchovies", - "level": 1 - }, - { - "item": "rs:sardine", - "text": "Sardine", - "level": 1 - }, - { - "item": "rs:karambwan", - "text": "Members: Karambwan", - "level": 1 - }, - { - "item": "rs:ugthanki_kebab", - "text": "Ugthanki kebab", - "level": 1 - }, - { - "item": "rs:herring", - "text": "Herring", - "level": 5 - }, - { - "item": "rs:mackerel", - "text": "Mackerel", - "level": 10 - }, - { - "item": "rs:thin_snail_meat", - "text": "Members: Thin snail", - "level": 12 - }, - { - "item": "rs:trout", - "text": "Trout", - "level": 15 - }, - { - "item": "rs:lean_snail_meat", - "text": "Members: Lean snail", - "level": 17 - }, - { - "item": "rs:cod", - "text": "Members: Cod", - "level": 18 - }, - { - "item": "rs:pike", - "text": "Pike", - "level": 20 - }, - { - "item": "rs:salmon", - "text": "Salmon", - "level": 25 - }, - { - "item": "rs:tuna", - "text": "Tuna", - "level": 30 - }, - { - "item": "rs:cooked_chompy", - "text": "Members: Cooked chompy", - "level": 30 - }, - { - "item": "rs:fish_cake", - "text": "Members: Fishcakes", - "level": 31 - }, - { - "item": "rs:cave_eel", - "text": "Members: Cave eel", - "level": 38 - }, - { - "item": "rs:lobster", - "text": "Lobster", - "level": 40 - }, - { - "item": "rs:jubbly", - "text": "Members: Jubbly", - "level": 41 - }, - { - "item": "rs:bass", - "text": "Members: Bass", - "level": 43 - }, - { - "item": "rs:swordfish", - "text": "Swordfish", - "level": 45 - }, - { - "item": "rs:lava_eel", - "text": "Members: Lava eel", - "level": 53 - }, - { - "item": "rs:shark", - "text": "Members: Shark", - "level": 80 - }, - { - "item": "rs:sea_turtle", - "text": "Members: Sea turtle", - "level": 82 - }, - { - "item": "rs:manta_ray", - "text": "Members: Manta ray", - "level": 90 - } - ] - }, - { - "name": "Bread", - "lines": [ - { - "item": "rs:bread", - "text": "Bread", - "level": 1 - }, - { - "item": "rs:pitta_bread", - "text": "Members: Pitta bread", - "level": 58 - } - ] - }, - { - "name": "Pies", - "lines": [ - { - "item": "rs:redberry_pie", - "text": "Redberry pie", - "level": 10 - }, - { - "item": "rs:meat_pie", - "text": "Meat pie", - "level": 20 - }, - { - "item": "rs:mud_pie", - "text": "Members: Mud pie", - "level": 29 - }, - { - "item": "rs:apple_pie", - "text": "Apple pie", - "level": 30 - }, - { - "item": "rs:garden_pie", - "text": "Members: Garden pie", - "level": 34 - }, - { - "item": "rs:fish_pie", - "text": "Members: Fish pie", - "level": 47 - }, - { - "item": "rs:admiral_pie", - "text": "Members: Admiral pie", - "level": 70 - }, - { - "item": "rs:wild_pie", - "text": "Members: Wild pie", - "level": 85 - }, - { - "item": "rs:summer_pie", - "text": "Members: Summer pie", - "level": 95 - } - ] - }, - { - "name": "Stews", - "lines": [ - { - "item": "rs:stew", - "text": "Stew", - "level": 25 - }, - { - "item": "rs:banana_stew", - "text": "Banana stew", - "level": 25 - }, - { - "item": "rs:spicy_stew", - "text": "Spicy stew", - "level": 25 - } - ] - }, - { - "name": "Pizzas", - "lines": [ - { - "item": "rs:plain_pizza", - "text": "Plain pizza", - "level": 35 - }, - { - "item": "rs:meat_pizza", - "text": "Meat pizza", - "level": 45 - }, - { - "item": "rs:anchovy_pizza", - "text": "Anchovy pizza", - "level": 55 - }, - { - "item": "rs:pineapple_pizza", - "text": "Members: Pineapple pizza", - "level": 65 - } - ] - }, - { - "name": "Cakes", - "lines": [ - { - "item": "rs:cake", - "text": "Cake", - "level": 40 - }, - { - "item": "rs:chocolate_cake", - "text": "Chocolate cake", - "level": 50 - } - ] - }, - { - "name": "Wine", - "lines": [ - { - "item": "rs:wine", - "text": "Wine", - "level": 35 - }, - { - "item": "rs:wine_of_zamorak", - "text": "Members: Wine of Zamorak", - "level": 65 - } - ] - }, - { - "name": "Hot drinks", - "lines": [ - { - "item": "rs:nettle_tea", - "text": "Nettle tea", - "level": 20 - } - ] - }, - { - "name": "Brewing", - "lines": [ - { - "item": "rs:cider", - "text": "Cider (4 Apple mush)", - "level": 14 - }, - { - "item": "rs:dwarven_stout", - "text": "Dwarven Stout (4 Hammerstone hops)", - "level": 19 - }, - { - "item": "rs:asgarnian_ale", - "text": "Asgarnian Ale (4 Asgarnian hops)", - "level": 24 - }, - { - "item": "rs:greenmans_ale", - "text": "Greenman's Ale (4 Harralander leaves)", - "level": 29 - }, - { - "item": "rs:wizards_mind_bomb", - "text": "Wizard's Mind Bomb (4 Yinillian hops)", - "level": 34 - }, - { - "item": "rs:dragon_bitter", - "text": "Dragon Bitter (4 Krandorian hops)", - "level": 39 - }, - { - "item": "rs:moonlight_mead", - "text": "Moonlight Mead (4 Bittercap mushrooms)", - "level": 44 - }, - { - "item": "rs:axemans_folly", - "text": "Axeman's Folly (1 Oak root)", - "level": 49 - }, - { - "item": "rs:chefs_delight", - "text": "Chef's Delight (4 Portions of chocolate dust)", - "level": 54 - }, - { - "item": "rs:slayers_respite", - "text": "Slayer's Respite (4 Wildblood hops)", - "level": 54 - } - ] - }, - { - "name": "Vegetable", - "lines": [ - { - "item": "rs:baked_potato", - "text": "Baked potato", - "level": 7 - }, - { - "item": "rs:spicy_sauce", - "text": "Spicy sauce (topping ingredient)", - "level": 9 - }, - { - "item": "rs:scrambled_egg", - "text": "Scrambled egg (topping ingredient)", - "level": 13 - }, - { - "item": "rs:scrambled_egg_and_tomato", - "text": "Scrambled egg and tomato (topping)", - "level": 23 - }, - { - "item": "rs:sweetcorn", - "text": "Sweetcorn", - "level": 28 - }, - { - "item": "rs:baked_potato_with_butter", - "text": "Baked potato with butter", - "level": 39 - }, - { - "item": "rs:fried_onion", - "text": "Fried onion (topping ingredient)", - "level": 42 - }, - { - "item": "rs:fried_mushroom", - "text": "Fried mushroom (topping ingredient)", - "level": 46 - }, - { - "item": "rs:baked_potato_with_butter_and_cheese", - "text": "Baked potato with butter and cheese", - "level": 47 - }, - { - "item": "rs:baked_potato_with_egg_and_tomato", - "text": "Baked potato with egg and tomato", - "level": 51 - }, - { - "item": "rs:fried_mushroom_and_onion", - "text": "Fried mushroom and onion (topping)", - "level": 57 - }, - { - "item": "rs:baked_potato_with_mushroom_and_onion", - "text": "Baked potato with mushroom and onion", - "level": 64 - }, - { - "item": "rs:tuna_and_sweetcorn", - "text": "Tuna and sweetcorn (topping)", - "level": 67 - }, - { - "item": "rs:baked_potato_with_tuna_and_sweetcorn", - "text": "Baked potato with tuna and sweetcorn", - "level": 68 - } - ] - }, - { - "name": "Diary", - "lines": [ - { - "item": "rs:butter", - "text": "Butter", - "level": 38 - }, - { - "item": "rs:cheese", - "text": "Cheese", - "level": 48 + "id": 129, + "name": "Cooking", + "members": false, + "sub_guides": [ + { + "name": "Meats", + "lines": [ + { + "item": "rs:meat", + "text": "Meat", + "level": 1 + }, + { + "item": "rs:shrimps", + "text": "Shrimp", + "level": 1 + }, + { + "item": "rs:chicken", + "text": "Chicken", + "level": 1 + }, + { + "item": "rs:anchovies", + "text": "Anchovies", + "level": 1 + }, + { + "item": "rs:sardine", + "text": "Sardine", + "level": 1 + }, + { + "item": "rs:karambwan", + "text": "Members: Karambwan", + "level": 1 + }, + { + "item": "rs:ugthanki_kebab", + "text": "Ugthanki kebab", + "level": 1 + }, + { + "item": "rs:herring", + "text": "Herring", + "level": 5 + }, + { + "item": "rs:mackerel", + "text": "Mackerel", + "level": 10 + }, + { + "item": "rs:thin_snail_meat", + "text": "Members: Thin snail", + "level": 12 + }, + { + "item": "rs:trout", + "text": "Trout", + "level": 15 + }, + { + "item": "rs:lean_snail_meat", + "text": "Members: Lean snail", + "level": 17 + }, + { + "item": "rs:cod", + "text": "Members: Cod", + "level": 18 + }, + { + "item": "rs:pike", + "text": "Pike", + "level": 20 + }, + { + "item": "rs:salmon", + "text": "Salmon", + "level": 25 + }, + { + "item": "rs:tuna", + "text": "Tuna", + "level": 30 + }, + { + "item": "rs:cooked_chompy", + "text": "Members: Cooked chompy", + "level": 30 + }, + { + "item": "rs:fish_cake", + "text": "Members: Fishcakes", + "level": 31 + }, + { + "item": "rs:cave_eel", + "text": "Members: Cave eel", + "level": 38 + }, + { + "item": "rs:lobster", + "text": "Lobster", + "level": 40 + }, + { + "item": "rs:jubbly", + "text": "Members: Jubbly", + "level": 41 + }, + { + "item": "rs:bass", + "text": "Members: Bass", + "level": 43 + }, + { + "item": "rs:swordfish", + "text": "Swordfish", + "level": 45 + }, + { + "item": "rs:lava_eel", + "text": "Members: Lava eel", + "level": 53 + }, + { + "item": "rs:shark", + "text": "Members: Shark", + "level": 80 + }, + { + "item": "rs:sea_turtle", + "text": "Members: Sea turtle", + "level": 82 + }, + { + "item": "rs:manta_ray", + "text": "Members: Manta ray", + "level": 90 + } + ] + }, + { + "name": "Bread", + "lines": [ + { + "item": "rs:bread", + "text": "Bread", + "level": 1 + }, + { + "item": "rs:pitta_bread", + "text": "Members: Pitta bread", + "level": 58 + } + ] + }, + { + "name": "Pies", + "lines": [ + { + "item": "rs:redberry_pie", + "text": "Redberry pie", + "level": 10 + }, + { + "item": "rs:meat_pie", + "text": "Meat pie", + "level": 20 + }, + { + "item": "rs:mud_pie", + "text": "Members: Mud pie", + "level": 29 + }, + { + "item": "rs:apple_pie", + "text": "Apple pie", + "level": 30 + }, + { + "item": "rs:garden_pie", + "text": "Members: Garden pie", + "level": 34 + }, + { + "item": "rs:fish_pie", + "text": "Members: Fish pie", + "level": 47 + }, + { + "item": "rs:admiral_pie", + "text": "Members: Admiral pie", + "level": 70 + }, + { + "item": "rs:wild_pie", + "text": "Members: Wild pie", + "level": 85 + }, + { + "item": "rs:summer_pie", + "text": "Members: Summer pie", + "level": 95 + } + ] + }, + { + "name": "Stews", + "lines": [ + { + "item": "rs:stew", + "text": "Stew", + "level": 25 + }, + { + "item": "rs:banana_stew", + "text": "Banana stew", + "level": 25 + }, + { + "item": "rs:spicy_stew", + "text": "Spicy stew", + "level": 25 + } + ] + }, + { + "name": "Pizzas", + "lines": [ + { + "item": "rs:plain_pizza", + "text": "Plain pizza", + "level": 35 + }, + { + "item": "rs:meat_pizza", + "text": "Meat pizza", + "level": 45 + }, + { + "item": "rs:anchovy_pizza", + "text": "Anchovy pizza", + "level": 55 + }, + { + "item": "rs:pineapple_pizza", + "text": "Members: Pineapple pizza", + "level": 65 + } + ] + }, + { + "name": "Cakes", + "lines": [ + { + "item": "rs:cake", + "text": "Cake", + "level": 40 + }, + { + "item": "rs:chocolate_cake", + "text": "Chocolate cake", + "level": 50 + } + ] + }, + { + "name": "Wine", + "lines": [ + { + "item": "rs:wine", + "text": "Wine", + "level": 35 + }, + { + "item": "rs:wine_of_zamorak", + "text": "Members: Wine of Zamorak", + "level": 65 + } + ] + }, + { + "name": "Hot drinks", + "lines": [ + { + "item": "rs:nettle_tea", + "text": "Nettle tea", + "level": 20 + } + ] + }, + { + "name": "Brewing", + "lines": [ + { + "item": "rs:cider", + "text": "Cider (4 Apple mush)", + "level": 14 + }, + { + "item": "rs:dwarven_stout", + "text": "Dwarven Stout (4 Hammerstone hops)", + "level": 19 + }, + { + "item": "rs:asgarnian_ale", + "text": "Asgarnian Ale (4 Asgarnian hops)", + "level": 24 + }, + { + "item": "rs:greenmans_ale", + "text": "Greenman's Ale (4 Harralander leaves)", + "level": 29 + }, + { + "item": "rs:wizards_mind_bomb", + "text": "Wizard's Mind Bomb (4 Yinillian hops)", + "level": 34 + }, + { + "item": "rs:dragon_bitter", + "text": "Dragon Bitter (4 Krandorian hops)", + "level": 39 + }, + { + "item": "rs:moonlight_mead", + "text": "Moonlight Mead (4 Bittercap mushrooms)", + "level": 44 + }, + { + "item": "rs:axemans_folly", + "text": "Axeman's Folly (1 Oak root)", + "level": 49 + }, + { + "item": "rs:chefs_delight", + "text": "Chef's Delight (4 Portions of chocolate dust)", + "level": 54 + }, + { + "item": "rs:slayers_respite", + "text": "Slayer's Respite (4 Wildblood hops)", + "level": 54 + } + ] + }, + { + "name": "Vegetable", + "lines": [ + { + "item": "rs:baked_potato", + "text": "Baked potato", + "level": 7 + }, + { + "item": "rs:spicy_sauce", + "text": "Spicy sauce (topping ingredient)", + "level": 9 + }, + { + "item": "rs:scrambled_egg", + "text": "Scrambled egg (topping ingredient)", + "level": 13 + }, + { + "item": "rs:scrambled_egg_and_tomato", + "text": "Scrambled egg and tomato (topping)", + "level": 23 + }, + { + "item": "rs:sweetcorn", + "text": "Sweetcorn", + "level": 28 + }, + { + "item": "rs:baked_potato_with_butter", + "text": "Baked potato with butter", + "level": 39 + }, + { + "item": "rs:fried_onion", + "text": "Fried onion (topping ingredient)", + "level": 42 + }, + { + "item": "rs:fried_mushroom", + "text": "Fried mushroom (topping ingredient)", + "level": 46 + }, + { + "item": "rs:baked_potato_with_butter_and_cheese", + "text": "Baked potato with butter and cheese", + "level": 47 + }, + { + "item": "rs:baked_potato_with_egg_and_tomato", + "text": "Baked potato with egg and tomato", + "level": 51 + }, + { + "item": "rs:fried_mushroom_and_onion", + "text": "Fried mushroom and onion (topping)", + "level": 57 + }, + { + "item": "rs:baked_potato_with_mushroom_and_onion", + "text": "Baked potato with mushroom and onion", + "level": 64 + }, + { + "item": "rs:tuna_and_sweetcorn", + "text": "Tuna and sweetcorn (topping)", + "level": 67 + }, + { + "item": "rs:baked_potato_with_tuna_and_sweetcorn", + "text": "Baked potato with tuna and sweetcorn", + "level": 68 + } + ] + }, + { + "name": "Diary", + "lines": [ + { + "item": "rs:butter", + "text": "Butter", + "level": 38 + }, + { + "item": "rs:cheese", + "text": "Cheese", + "level": 48 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/crafting.json b/src/plugins/skills/skill-guides/crafting.json index 97dc6c8e0..2b3985071 100644 --- a/src/plugins/skills/skill-guides/crafting.json +++ b/src/plugins/skills/skill-guides/crafting.json @@ -3,513 +3,520 @@ "name": "Crafting", "members": false, "sub_guides": [ - { - "name": "Weaving", - "lines": [ - { - "item": "rs:vegetable_sack", - "text": "Vegetable sack", - "level": 21 - }, - { - "item": "rs:drift_net", - "text": "Drift net", - "level": 26 - }, - { - "item": "rs:fruit_basket", - "text": "Fruit basket", - "level": 36 - } - ] - },{ - "name": "Armour", - "lines": [ - { - "item": "rs:leather_gloves", - "text": "Leather gloves", - "level": 1 - }, - { - "item": "rs:leather_boots", - "text": "Leather boots", - "level": 7 - }, - { - "item": "rs:leather_cowl", - "text": "Leather cowl", - "level": 5 - }, - { - "item": "rs:leather_vambraces", - "text": "Leather vambraces", - "level": 11 - }, - { - "item": "rs:leather_body", - "text": "Leather body", - "level": 14 - }, - { - "item": "rs:snelmet", - "text": "Members: Snail helmet", - "level": 15 - }, - { - "item": "rs:crab_shell_armour", - "text": "Crab shell armour", - "level": 15 - }, - { - "item": "rs:leather_chaps", - "text": "Leather chaps", - "level": 18 - }, - { - "item": "rs:hard_leather_body", - "text": "Hard leather body", - "level": 28 - }, - { - "item": "rs:broodoo_shield", - "text": "Members: Broodoo shield", - "level": 35 - }, - { - "item": "rs:coif", - "text": "Members: Coif", - "level": 38 - }, - { - "item": "rs:studded_body", - "text": "Members: Studded body", - "level": 41 - }, - { - "item": "rs:studded_chaps", - "text": "Members: Studded chaps", - "level": 44 - }, - { - "item": "rs:snakeskin_boots", - "text": "Members: Snakeskin boots", - "level": 45 - }, - { - "item": "rs:snakeskin_vambraces", - "text": "Members: Snakeskin vambraces", - "level": 47 - }, - { - "item": "rs:snakeskin_bandana", - "text": "Members: Snakeskin Bandana", - "level": 48 - }, - { - "item": "rs:snakeskin_chaps", - "text": "Members: Snakeskin chaps", - "level": 51 - }, - { - "item": "rs:snakeskin_body", - "text": "Members: Snakeskin body", - "level": 53 - }, - { - "item": "rs:green_dragonhide_vambraces", - "text": "Members: Green Dragonhide vambraces", - "level": 57 - }, - { - "item": "rs:green_dragonhide_chaps", - "text": "Members: Green dragonhide chaps", - "level": 60 - }, - { - "item": "rs:splitbark_gauntlets", - "text": "Members: Splitbark gauntlets", - "level": 60 - }, - { - "item": "rs:splitbark_boots", - "text": "Members: Splitbark boots", - "level": 60 - }, - { - "item": "rs:splitbark_helm", - "text": "Members: Splitbark helm", - "level": 61 - }, - { - "item": "rs:splitbark_body", - "text": "Members: Splitbark body", - "level": 62 - }, - { - "item": "rs:splitbark_legs", - "text": "Members: Splitbark legs", - "level": 62 - }, - { - "item": "rs:green_dragonhide_chaps", - "text": "Members: Green dragonhide chaps", - "level": 63 - }, - { - "item": "rs:blue_dragonhide_chaps", - "text": "Members: Blue dragonhide chaps", - "level": 66 - }, - { - "item": "rs:blue_dragonhide_chaps", - "text": "Members: Blue dragonhide chaps", - "level": 68 - }, - { - "item": "rs:blue_dragonhide_body", - "text": "Members: Blue dragonhide body", - "level": 71 - }, - { - "item": "rs:red_dragonhide_vambraces", - "text": "Members: Red dragonhide vambraces", - "level": 73 - }, - { - "item": "rs:red_dragonhide_chaps", - "text": "Members: Red dragonhide chaps", - "level": 75 - }, - { - "item": "rs:red_dragonhide_body", - "text": "Members: Red dragonhide body", - "level": 77 - }, - { - "item": "rs:black_dragonhide_vambraces", - "text": "Members: Snakeskin chaps", - "level": 79 - }, - { - "item": "rs:black_dragonhide_chaps", - "text": "Members: Snakeskin chaps", - "level": 82 - }, - { - "item": "rs:black_dragonhide_body", - "text": "Members: Black dragonhide body", - "level": 84 - } - ] - },{ - "name": "Spinning", - "lines": [ - { - "item": "rs:wool", - "text": "Wool", - "level": 1 - }, - { - "item": "rs:bow_strings", - "text": "Members: Flax into bow strings", - "level": 10 - }, - { - "item": "rs:sinew_strings", - "text": "Members: Sinew into crossbow strings", - "level": 10 - }, - { - "item": "rs:magic_strings", - "text": "Members: Magic tree roots into magic strings", - "level": 19 - }, - { - "item": "rs:yak_hair", - "text": "Members: Yak hair into rope", - "level": 30 - } - ] - },{ - "name": "Pottery", - "lines": [ - { - "item": "rs:pot", - "text": "Pot", - "level": 1 - }, - { - "item": "rs:pie_dish", - "text": "Pie dish", - "level": 7 - }, - { - "item": "rs:bowl", - "text": "Bowl", - "level": 8 - }, { - "item": "rs:plant_pot", - "text": "Members: Plant pot", - "level": 19 - }, { - "item": "rs:pot_lid", - "text": "Members: Pot lid", - "level": 25 - } - ] - },{ - "name": "Glass", - "lines": [ - { - "item": "rs:beer_glass", - "text": "Beer Glass", - "level": 1 - }, - { - "item": "rs:candle_lantern", - "text": "Candle lantern", - "level": 4 - }, - { - "item": "rs:oil_lamp", - "text": "Oil lamp", - "level": 12 - }, - { - "item": "rs:oil_lantern", - "text": "Oil lantern", - "level": 26 - }, - { - "item": "rs:vial", - "text": "Vial", - "level": 33 - }, - { - "item": "rs:fishbowl", - "text": "Fishbowl", - "level": 42 - }, - { - "item": "rs:glass_orb", - "text": "Glass orb", - "level": 46 - }, - { - "item": "rs:bullseye_lantern_lens", - "text": "Bullsye lantern lens", - "level": 49 - } - ] - },{ - "name": "Jewellery", - "lines": [ - { - "item": "rs:cut_opal", - "text": "Cut opal", - "level": 1 - }, - { - "item": "rs:opal_ring", - "text": "Opal ring", - "level": 1 - }, - { - "item": "rs:polished_buttons", - "text": "Polished buttons", - "level": 3 - }, - { - "item": "rs:gold_ring", - "text": "Gold ring", - "level": 5 - }, - { - "item": "rs:gold_necklace", - "text": "Gold necklace", - "level": 6 - }, - { - "item": "rs:gold_amulet", - "text": "Gold amulet", - "level": 8 - }, - { - "item": "rs:cut_jade", - "text": "Cut jade", - "level": 13 - }, - { - "item": "rs:jade_ring", - "text": "Jade ring", - "level": 13 - }, - { - "item": "rs:holy_symbol", - "text": "Holy symbol", - "level": 16 - }, - { - "item": "rs:cut_red_topaz", - "text": "Members: Cut red topaz", - "level": 16 - }, - { - "item": "rs:cut_sapphire", - "text": "Cut sapphire", - "level": 20 - }, - { - "item": "rs:sapphire_ring", - "text": "Sapphire ring", - "level": 20 - }, - { - "item": "rs:sapphire_necklace", - "text": "Sapphire necklace", - "level": 22 - }, - { - "item": "rs:tiara", - "text": "Tiara", - "level": 23 - }, - { - "item": "rs:sapphire_amulet", - "text": "Sapphire amulet", - "level": 24 - }, - { - "item": "rs:cut_emerald", - "text": "Cut emerald", - "level": 27 - }, - { - "item": "rs:emerald_ring", - "text": "Emerald ring", - "level": 27 - }, - { - "item": "rs:emerald_necklace", - "text": "Emerald necklace", - "level": 29 - }, - { - "item": "rs:emerald_amulet", - "text": "Emerald amulet", - "level": 31 - }, - { - "item": "rs:cut_ruby", - "text": "Cut ruby", - "level": 34 - }, - { - "item": "rs:ruby_ring", - "text": "Ruby ring", - "level": 34 - }, - { - "item": "rs:ruby_necklace", - "text": "Ruby necklace", - "level": 40 - }, - { - "item": "rs:cut_diamond", - "text": "Cut diamond", - "level": 43 - }, - { - "item": "rs:diamond_ring", - "text": "Diamond ring", - "level": 43 - }, - { - "item": "rs:ruby_amulet", - "text": "Ruby amulet", - "level": 50 - }, - { - "item": "rs:cut_dragonstone", - "text": "Members: Cut Dragonstone", - "level": 55 - }, - { - "item": "rs:dragonstone_ring", - "text": "Members: Dragonstone ring", - "level": 55 - }, - { - "item": "rs:diamond_necklace", - "text": "Diamond necklace", - "level": 56 - }, - { - "item": "rs:cut_onyx", - "text": "Members: Cut onyx", - "level": 67 - }, - { - "item": "rs:onyx_ring", - "text": "Onyx Ring", - "level": 67 - }, - { - "item": "rs:diamond_amulet", - "text": "Diamond amulet", - "level": 70 - }, - { - "item": "rs:dragonstone_amulet", - "text": "Members: Dragonstone amulet", - "level": 80 - }, - { - "item": "rs:onyx_necklace", - "text": "Members Onyx necklace", - "level": 82 - }, - { - "item": "rs:onyx_amulet", - "text": "Members: Onyx amulet", - "level": 90 - } - ] - }, { - "name": "Weaponry", - "lines": [ - { - "item": "rs:silver_sickle", - "text": "Silver sickle", - "level": 18 - }, - { - "item": "rs:silver_crossbow_bolts", - "text": "Silver crossbow bolts", - "level": 21 - }, - { - "item": "rs:water_battlestaff", - "text": "Water battlestaf", - "level": 54 - }, - { - "item": "rs:earth_battlestaff", - "text": "Earth battlestaf", - "level": 58 - }, - { - "item": "rs:fire_battlestaff", - "text": "Fire battlestaf", - "level": 62 - }, - { - "item": "rs:air_battlestaff", - "text": "Air battlestaf", - "level": 66 - } - ] - } + { + "name": "Weaving", + "lines": [ + { + "item": "rs:vegetable_sack", + "text": "Vegetable sack", + "level": 21 + }, + { + "item": "rs:drift_net", + "text": "Drift net", + "level": 26 + }, + { + "item": "rs:fruit_basket", + "text": "Fruit basket", + "level": 36 + } + ] + }, + { + "name": "Armour", + "lines": [ + { + "item": "rs:leather_gloves", + "text": "Leather gloves", + "level": 1 + }, + { + "item": "rs:leather_boots", + "text": "Leather boots", + "level": 7 + }, + { + "item": "rs:leather_cowl", + "text": "Leather cowl", + "level": 5 + }, + { + "item": "rs:leather_vambraces", + "text": "Leather vambraces", + "level": 11 + }, + { + "item": "rs:leather_body", + "text": "Leather body", + "level": 14 + }, + { + "item": "rs:snelmet", + "text": "Members: Snail helmet", + "level": 15 + }, + { + "item": "rs:crab_shell_armour", + "text": "Crab shell armour", + "level": 15 + }, + { + "item": "rs:leather_chaps", + "text": "Leather chaps", + "level": 18 + }, + { + "item": "rs:hard_leather_body", + "text": "Hard leather body", + "level": 28 + }, + { + "item": "rs:broodoo_shield", + "text": "Members: Broodoo shield", + "level": 35 + }, + { + "item": "rs:coif", + "text": "Members: Coif", + "level": 38 + }, + { + "item": "rs:studded_body", + "text": "Members: Studded body", + "level": 41 + }, + { + "item": "rs:studded_chaps", + "text": "Members: Studded chaps", + "level": 44 + }, + { + "item": "rs:snakeskin_boots", + "text": "Members: Snakeskin boots", + "level": 45 + }, + { + "item": "rs:snakeskin_vambraces", + "text": "Members: Snakeskin vambraces", + "level": 47 + }, + { + "item": "rs:snakeskin_bandana", + "text": "Members: Snakeskin Bandana", + "level": 48 + }, + { + "item": "rs:snakeskin_chaps", + "text": "Members: Snakeskin chaps", + "level": 51 + }, + { + "item": "rs:snakeskin_body", + "text": "Members: Snakeskin body", + "level": 53 + }, + { + "item": "rs:green_dragonhide_vambraces", + "text": "Members: Green Dragonhide vambraces", + "level": 57 + }, + { + "item": "rs:green_dragonhide_chaps", + "text": "Members: Green dragonhide chaps", + "level": 60 + }, + { + "item": "rs:splitbark_gauntlets", + "text": "Members: Splitbark gauntlets", + "level": 60 + }, + { + "item": "rs:splitbark_boots", + "text": "Members: Splitbark boots", + "level": 60 + }, + { + "item": "rs:splitbark_helm", + "text": "Members: Splitbark helm", + "level": 61 + }, + { + "item": "rs:splitbark_body", + "text": "Members: Splitbark body", + "level": 62 + }, + { + "item": "rs:splitbark_legs", + "text": "Members: Splitbark legs", + "level": 62 + }, + { + "item": "rs:green_dragonhide_chaps", + "text": "Members: Green dragonhide chaps", + "level": 63 + }, + { + "item": "rs:blue_dragonhide_chaps", + "text": "Members: Blue dragonhide chaps", + "level": 66 + }, + { + "item": "rs:blue_dragonhide_chaps", + "text": "Members: Blue dragonhide chaps", + "level": 68 + }, + { + "item": "rs:blue_dragonhide_body", + "text": "Members: Blue dragonhide body", + "level": 71 + }, + { + "item": "rs:red_dragonhide_vambraces", + "text": "Members: Red dragonhide vambraces", + "level": 73 + }, + { + "item": "rs:red_dragonhide_chaps", + "text": "Members: Red dragonhide chaps", + "level": 75 + }, + { + "item": "rs:red_dragonhide_body", + "text": "Members: Red dragonhide body", + "level": 77 + }, + { + "item": "rs:black_dragonhide_vambraces", + "text": "Members: Snakeskin chaps", + "level": 79 + }, + { + "item": "rs:black_dragonhide_chaps", + "text": "Members: Snakeskin chaps", + "level": 82 + }, + { + "item": "rs:black_dragonhide_body", + "text": "Members: Black dragonhide body", + "level": 84 + } + ] + }, + { + "name": "Spinning", + "lines": [ + { + "item": "rs:wool", + "text": "Wool", + "level": 1 + }, + { + "item": "rs:bow_strings", + "text": "Members: Flax into bow strings", + "level": 10 + }, + { + "item": "rs:sinew_strings", + "text": "Members: Sinew into crossbow strings", + "level": 10 + }, + { + "item": "rs:magic_strings", + "text": "Members: Magic tree roots into magic strings", + "level": 19 + }, + { + "item": "rs:yak_hair", + "text": "Members: Yak hair into rope", + "level": 30 + } + ] + }, + { + "name": "Pottery", + "lines": [ + { + "item": "rs:pot", + "text": "Pot", + "level": 1 + }, + { + "item": "rs:pie_dish", + "text": "Pie dish", + "level": 7 + }, + { + "item": "rs:bowl", + "text": "Bowl", + "level": 8 + }, + { + "item": "rs:plant_pot", + "text": "Members: Plant pot", + "level": 19 + }, + { + "item": "rs:pot_lid", + "text": "Members: Pot lid", + "level": 25 + } + ] + }, + { + "name": "Glass", + "lines": [ + { + "item": "rs:beer_glass", + "text": "Beer Glass", + "level": 1 + }, + { + "item": "rs:candle_lantern", + "text": "Candle lantern", + "level": 4 + }, + { + "item": "rs:oil_lamp", + "text": "Oil lamp", + "level": 12 + }, + { + "item": "rs:oil_lantern", + "text": "Oil lantern", + "level": 26 + }, + { + "item": "rs:vial", + "text": "Vial", + "level": 33 + }, + { + "item": "rs:fishbowl", + "text": "Fishbowl", + "level": 42 + }, + { + "item": "rs:glass_orb", + "text": "Glass orb", + "level": 46 + }, + { + "item": "rs:bullseye_lantern_lens", + "text": "Bullsye lantern lens", + "level": 49 + } + ] + }, + { + "name": "Jewellery", + "lines": [ + { + "item": "rs:cut_opal", + "text": "Cut opal", + "level": 1 + }, + { + "item": "rs:opal_ring", + "text": "Opal ring", + "level": 1 + }, + { + "item": "rs:polished_buttons", + "text": "Polished buttons", + "level": 3 + }, + { + "item": "rs:gold_ring", + "text": "Gold ring", + "level": 5 + }, + { + "item": "rs:gold_necklace", + "text": "Gold necklace", + "level": 6 + }, + { + "item": "rs:gold_amulet", + "text": "Gold amulet", + "level": 8 + }, + { + "item": "rs:cut_jade", + "text": "Cut jade", + "level": 13 + }, + { + "item": "rs:jade_ring", + "text": "Jade ring", + "level": 13 + }, + { + "item": "rs:holy_symbol", + "text": "Holy symbol", + "level": 16 + }, + { + "item": "rs:cut_red_topaz", + "text": "Members: Cut red topaz", + "level": 16 + }, + { + "item": "rs:cut_sapphire", + "text": "Cut sapphire", + "level": 20 + }, + { + "item": "rs:sapphire_ring", + "text": "Sapphire ring", + "level": 20 + }, + { + "item": "rs:sapphire_necklace", + "text": "Sapphire necklace", + "level": 22 + }, + { + "item": "rs:tiara", + "text": "Tiara", + "level": 23 + }, + { + "item": "rs:sapphire_amulet", + "text": "Sapphire amulet", + "level": 24 + }, + { + "item": "rs:cut_emerald", + "text": "Cut emerald", + "level": 27 + }, + { + "item": "rs:emerald_ring", + "text": "Emerald ring", + "level": 27 + }, + { + "item": "rs:emerald_necklace", + "text": "Emerald necklace", + "level": 29 + }, + { + "item": "rs:emerald_amulet", + "text": "Emerald amulet", + "level": 31 + }, + { + "item": "rs:cut_ruby", + "text": "Cut ruby", + "level": 34 + }, + { + "item": "rs:ruby_ring", + "text": "Ruby ring", + "level": 34 + }, + { + "item": "rs:ruby_necklace", + "text": "Ruby necklace", + "level": 40 + }, + { + "item": "rs:cut_diamond", + "text": "Cut diamond", + "level": 43 + }, + { + "item": "rs:diamond_ring", + "text": "Diamond ring", + "level": 43 + }, + { + "item": "rs:ruby_amulet", + "text": "Ruby amulet", + "level": 50 + }, + { + "item": "rs:cut_dragonstone", + "text": "Members: Cut Dragonstone", + "level": 55 + }, + { + "item": "rs:dragonstone_ring", + "text": "Members: Dragonstone ring", + "level": 55 + }, + { + "item": "rs:diamond_necklace", + "text": "Diamond necklace", + "level": 56 + }, + { + "item": "rs:cut_onyx", + "text": "Members: Cut onyx", + "level": 67 + }, + { + "item": "rs:onyx_ring", + "text": "Onyx Ring", + "level": 67 + }, + { + "item": "rs:diamond_amulet", + "text": "Diamond amulet", + "level": 70 + }, + { + "item": "rs:dragonstone_amulet", + "text": "Members: Dragonstone amulet", + "level": 80 + }, + { + "item": "rs:onyx_necklace", + "text": "Members Onyx necklace", + "level": 82 + }, + { + "item": "rs:onyx_amulet", + "text": "Members: Onyx amulet", + "level": 90 + } + ] + }, + { + "name": "Weaponry", + "lines": [ + { + "item": "rs:silver_sickle", + "text": "Silver sickle", + "level": 18 + }, + { + "item": "rs:silver_crossbow_bolts", + "text": "Silver crossbow bolts", + "level": 21 + }, + { + "item": "rs:water_battlestaff", + "text": "Water battlestaf", + "level": 54 + }, + { + "item": "rs:earth_battlestaff", + "text": "Earth battlestaf", + "level": 58 + }, + { + "item": "rs:fire_battlestaff", + "text": "Fire battlestaf", + "level": 62 + }, + { + "item": "rs:air_battlestaff", + "text": "Air battlestaf", + "level": 66 + } + ] + } ] - } - \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/defence.json b/src/plugins/skills/skill-guides/defence.json index 9b6dd651d..ef85d1c43 100644 --- a/src/plugins/skills/skill-guides/defence.json +++ b/src/plugins/skills/skill-guides/defence.json @@ -1,97 +1,97 @@ { - "id": 124, - "name": "Defence", - "members": false, - "sub_guides": [ - { - "name": "Armour", - "lines": [ - { - "item": "rs:bronze_medium_helm", - "text": "Bronze armour\\nwield any bronze equipment", - "level": 1 - }, - { - "item": "rs:iron_medium_helm", - "text": "Iron armour\\nwield any iron equipment", - "level": 1 - }, - { - "item": "rs:steel_medium_helm", - "text": "Steel armour\\nwield any steel equipment", - "level": 5 - }, - { - "item": "rs:black_medium_helm", - "text": "Black armour\\nwield any black equipment", - "level": 10 - }, - { - "item": "rs:white_medium_helm", - "text": "Members: white armour\\nwield any white equipment", - "level": 10 - }, - { - "item": "rs:initiate_medium_helm", - "text": "Members: Initiate armour\\n(after Recruitment Drive, with 10 Prayer)", - "level": 20 - }, - { - "item": "rs:mithril_medium_helm", - "text": "Mithril armour\\nwield any mithril equipment", - "level": 20 - }, - { - "item": "rs:adamant_medium_helm", - "text": "Adamant armour\\nwield any adamant equipment", - "level": 30 - }, - { - "item": "rs:proselyte_medium_helm", - "text": "Members: Proselyte armour\\n(after Slug Menance, with 20 Prayer)", - "level": 30 - }, - { - "item": "rs:rune_medium_helm", - "text": "Rune armour\\nwield any rune equipment", - "level": 40 - }, - { - "item": "rs:rock_shell_helm", - "text": "Members: Rock-shell armour\\n(after completing Fremennik Trials)", - "level": 40 - }, - { - "item": "rs:berserker_helm", - "text": "Members: Fremennik helmets\\n(after completing Fremennik Trials)", - "level": 45 - }, - { - "item": "rs:granite_shield", - "text": "Granite armour\\nwield any granite equipment", - "level": 50 - }, - { - "item": "rs:helm_of_neitiznot", - "text": "Members: Helm of neitiznot\\n(after Fremennik Isles)", - "level": 55 - }, - { - "item": "rs:Members: Dragon armour", - "text": "Dragon armour\\nwield any dragon equipment", - "level": 60 - }, - { - "item": "rs:3rd_age_full_helmet", - "text": "3rd Age armour\\nwield any 3rd Age equipment", - "level": 65 - }, - { - "item": "rs:torags_helmet", - "text": "Barrows armour\\nwield any Barrows equipment", - "level": 70 + "id": 124, + "name": "Defence", + "members": false, + "sub_guides": [ + { + "name": "Armour", + "lines": [ + { + "item": "rs:bronze_medium_helm", + "text": "Bronze armour\\nwield any bronze equipment", + "level": 1 + }, + { + "item": "rs:iron_medium_helm", + "text": "Iron armour\\nwield any iron equipment", + "level": 1 + }, + { + "item": "rs:steel_medium_helm", + "text": "Steel armour\\nwield any steel equipment", + "level": 5 + }, + { + "item": "rs:black_medium_helm", + "text": "Black armour\\nwield any black equipment", + "level": 10 + }, + { + "item": "rs:white_medium_helm", + "text": "Members: white armour\\nwield any white equipment", + "level": 10 + }, + { + "item": "rs:initiate_medium_helm", + "text": "Members: Initiate armour\\n(after Recruitment Drive, with 10 Prayer)", + "level": 20 + }, + { + "item": "rs:mithril_medium_helm", + "text": "Mithril armour\\nwield any mithril equipment", + "level": 20 + }, + { + "item": "rs:adamant_medium_helm", + "text": "Adamant armour\\nwield any adamant equipment", + "level": 30 + }, + { + "item": "rs:proselyte_medium_helm", + "text": "Members: Proselyte armour\\n(after Slug Menance, with 20 Prayer)", + "level": 30 + }, + { + "item": "rs:rune_medium_helm", + "text": "Rune armour\\nwield any rune equipment", + "level": 40 + }, + { + "item": "rs:rock_shell_helm", + "text": "Members: Rock-shell armour\\n(after completing Fremennik Trials)", + "level": 40 + }, + { + "item": "rs:berserker_helm", + "text": "Members: Fremennik helmets\\n(after completing Fremennik Trials)", + "level": 45 + }, + { + "item": "rs:granite_shield", + "text": "Granite armour\\nwield any granite equipment", + "level": 50 + }, + { + "item": "rs:helm_of_neitiznot", + "text": "Members: Helm of neitiznot\\n(after Fremennik Isles)", + "level": 55 + }, + { + "item": "rs:Members: Dragon armour", + "text": "Dragon armour\\nwield any dragon equipment", + "level": 60 + }, + { + "item": "rs:3rd_age_full_helmet", + "text": "3rd Age armour\\nwield any 3rd Age equipment", + "level": 65 + }, + { + "item": "rs:torags_helmet", + "text": "Barrows armour\\nwield any Barrows equipment", + "level": 70 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/farming.json b/src/plugins/skills/skill-guides/farming.json index d903cf7c9..a23c855e8 100644 --- a/src/plugins/skills/skill-guides/farming.json +++ b/src/plugins/skills/skill-guides/farming.json @@ -3,430 +3,440 @@ "name": "Farming", "members": true, "sub_guides": [ - { - "name": "Allotments", - "lines": [ - { - "item": "rs:potatoes", - "text": "Potatoes\\nPayment: Compost x2", - "level": 1 - }, - { - "item": "rs:onions", - "text": "Onions\\nPayment: Potatoes(10)", - "level": 5 - }, - { - "item": "rs:cabbages", - "text": "Cabbages\\nPayment: Onions(10)", - "level": 7 - }, - { - "item": "rs:tomatoes", - "text": "Tomatoes\\nPayment: Cabbages(10)", - "level": 12 - }, - { - "item": "rs:sweetcorn", - "text": "Sweetcorn\\nPayment: Jute fibre x10", - "level": 20 - }, - { - "item": "rs:strawberries", - "text": "Strawberries\\nPayment: Apples(5)", - "level": 31 - }, - { - "item": "rs:watermelons", - "text": "Watermelons\\nPayment: Curry leaf x10", - "level": 47 - }, - { - "item": "rs:snape_grass", - "text": "Snape grass\\nPayment: Jangerberries x5", - "level": 61 - } - ] - },{ - "name": "Hops", - "lines": [ - { - "item": "rs:barley", - "text": "Barley\\nPayment: Compost x3", - "level": 3 - }, - { - "item": "rs:hammerstone_hops", - "text": "Hammerstone hops\\nPayment: Marigolds", - "level": 4 - }, - { - "item": "rs:asgarnian_hops", - "text": "Asgarnian hops\\nPayment: Onions(10)", - "level": 8 - }, - { - "item": "rs:jute_plants", - "text": "Jute plants\\nPayment: Barley malt x6", - "level": 13 - }, - { - "item": "rs:yanillian_hops", - "text": "Yanillian hops\\nPayment: Tomatoes(5)", - "level": 16 - }, - { - "item": "rs:krandorian_hops", - "text": "Krandorian hops\\nPayment: Cabbages(10) x3", - "level": 21 - }, - { - "item": "rs:wildblood_hops", - "text": "Wildblood hops\\nPayment: Nasturtiums", - "level": 28 - } - ] - },{ - "name": "Trees", - "lines": [ - { - "item": "rs:oak_trees", - "text": "Oak trees\\nPayment: Tomatoes(5)", - "level": 15 - }, - { - "item": "rs:willow_trees", - "text": "Willow trees\\nPayment: Apples(5)", - "level": 30 - }, - { - "item": "rs:maple_trees", - "text": "Mapple trees\\nPayment: Oranges(5)", - "level": 45 - }, - { - "item": "rs:yew_trees", - "text": "Yew trees\\nPayment: Cactus spine x10", - "level": 60 - }, - { - "item": "rs:magic_trees", - "text": "Magic trees\\nPayment: Coconut x25", - "level": 75 - } - ] - } ,{ - "name": "Fruit Trees", - "lines": [ - { - "item": "rs:apple_trees", - "text": "Apple trees\\nPayment: Sweetcorn x9", - "level": 27 - }, - { - "item": "rs:banana_trees", - "text": "Banana trees\\nPayment: Apples(5) x4", - "level": 33 - }, - { - "item": "rs:orange_trees", - "text": "Orange trees\\nPayment: Strawberries(5) x3", - "level": 39 - }, - { - "item": "rs:curry_trees", - "text": "Curry trees\\nPayment: Bananas(5) x3", - "level": 42 - }, - { - "item": "rs:pineapple_trees", - "text": "Pineapple trees\\nPayment: Watermelon x10", - "level": 51 - }, - { - "item": "rs:papaya_trees", - "text": "Papaya trees\\nPayment: Pineapple x10", - "level": 57 - }, - { - "item": "rs:palm_trees", - "text": "Palm trees\\nPayment: Papaya fruit x15", - "level": 68 - } + { + "name": "Allotments", + "lines": [ + { + "item": "rs:potatoes", + "text": "Potatoes\\nPayment: Compost x2", + "level": 1 + }, + { + "item": "rs:onions", + "text": "Onions\\nPayment: Potatoes(10)", + "level": 5 + }, + { + "item": "rs:cabbages", + "text": "Cabbages\\nPayment: Onions(10)", + "level": 7 + }, + { + "item": "rs:tomatoes", + "text": "Tomatoes\\nPayment: Cabbages(10)", + "level": 12 + }, + { + "item": "rs:sweetcorn", + "text": "Sweetcorn\\nPayment: Jute fibre x10", + "level": 20 + }, + { + "item": "rs:strawberries", + "text": "Strawberries\\nPayment: Apples(5)", + "level": 31 + }, + { + "item": "rs:watermelons", + "text": "Watermelons\\nPayment: Curry leaf x10", + "level": 47 + }, + { + "item": "rs:snape_grass", + "text": "Snape grass\\nPayment: Jangerberries x5", + "level": 61 + } + ] + }, + { + "name": "Hops", + "lines": [ + { + "item": "rs:barley", + "text": "Barley\\nPayment: Compost x3", + "level": 3 + }, + { + "item": "rs:hammerstone_hops", + "text": "Hammerstone hops\\nPayment: Marigolds", + "level": 4 + }, + { + "item": "rs:asgarnian_hops", + "text": "Asgarnian hops\\nPayment: Onions(10)", + "level": 8 + }, + { + "item": "rs:jute_plants", + "text": "Jute plants\\nPayment: Barley malt x6", + "level": 13 + }, + { + "item": "rs:yanillian_hops", + "text": "Yanillian hops\\nPayment: Tomatoes(5)", + "level": 16 + }, + { + "item": "rs:krandorian_hops", + "text": "Krandorian hops\\nPayment: Cabbages(10) x3", + "level": 21 + }, + { + "item": "rs:wildblood_hops", + "text": "Wildblood hops\\nPayment: Nasturtiums", + "level": 28 + } + ] + }, + { + "name": "Trees", + "lines": [ + { + "item": "rs:oak_trees", + "text": "Oak trees\\nPayment: Tomatoes(5)", + "level": 15 + }, + { + "item": "rs:willow_trees", + "text": "Willow trees\\nPayment: Apples(5)", + "level": 30 + }, + { + "item": "rs:maple_trees", + "text": "Mapple trees\\nPayment: Oranges(5)", + "level": 45 + }, + { + "item": "rs:yew_trees", + "text": "Yew trees\\nPayment: Cactus spine x10", + "level": 60 + }, + { + "item": "rs:magic_trees", + "text": "Magic trees\\nPayment: Coconut x25", + "level": 75 + } + ] + }, + { + "name": "Fruit Trees", + "lines": [ + { + "item": "rs:apple_trees", + "text": "Apple trees\\nPayment: Sweetcorn x9", + "level": 27 + }, + { + "item": "rs:banana_trees", + "text": "Banana trees\\nPayment: Apples(5) x4", + "level": 33 + }, + { + "item": "rs:orange_trees", + "text": "Orange trees\\nPayment: Strawberries(5) x3", + "level": 39 + }, + { + "item": "rs:curry_trees", + "text": "Curry trees\\nPayment: Bananas(5) x3", + "level": 42 + }, + { + "item": "rs:pineapple_trees", + "text": "Pineapple trees\\nPayment: Watermelon x10", + "level": 51 + }, + { + "item": "rs:papaya_trees", + "text": "Papaya trees\\nPayment: Pineapple x10", + "level": 57 + }, + { + "item": "rs:palm_trees", + "text": "Palm trees\\nPayment: Papaya fruit x15", + "level": 68 + } + ] + }, + { + "name": "Bushes", + "lines": [ + { + "item": "rs:redberry_bushes", + "text": "Redberry bushes\\nPayment: Cabbages(10) x4", + "level": 10 + }, + { + "item": "rs:cadavaberry_bushes", + "text": "Cadavanerry bushes\\nPayment: Tomatoes(5) x3", + "level": 22 + }, + { + "item": "rs:dwellberry_bushes", + "text": "Dwellberry bushes\\nPayment: Strawberries(5) x3", + "level": 36 + }, + { + "item": "rs:jangerberry_bushes", + "text": "Jangerberry bushes\\nPayment: Watermelon x6", + "level": 48 + }, + { + "item": "rs:white_berry_bushes", + "text": "White berry bushes\\nPayment: Mushroom x8", + "level": 59 + }, + { + "item": "rs:poison_ivy_bushes", + "text": "Poison ivy bushes", + "level": 70 + } + ] + }, + { + "name": "Flowers", + "lines": [ + { + "item": "rs:marigolds", + "text": "Marigolds\\nProtects onions, tomatoes and potatoes", + "level": 2 + }, + { + "item": "rs:rosemary", + "text": "Rosemary\\nProtects cabbages from disease", + "level": 22 + }, + { + "item": "scarecrow", + "text": "Make and place a scarecrow\\nProtects sweetcorn from birds", + "level": 23 + }, + { + "item": "rs:nasturtiums", + "text": "Nasturtiums\\nProtects watermelons from disease", + "level": 24 + }, + { + "item": "rs:woad", + "text": "Woad", + "level": 25 + }, + { + "item": "rs:limpwurt_root", + "text": "Limpwurt plants", + "level": 26 + }, + { + "item": "rs:white_lily", + "text": "White lily\\nProtects all allotment crops", + "level": 58 + } + ] + }, + { + "name": "Herbs", + "lines": [ + { + "item": "rs:guam_leaf", + "text": "Guam leaf", + "level": 9 + }, + { + "item": "rs:marrentill", + "text": "Marrentill", + "level": 14 + }, + { + "item": "tarromin", + "text": "Tarromin", + "level": 19 + }, + { + "item": "rs:harralander", + "text": "Harralander", + "level": 26 + }, + { + "item": "rs:goutweed", + "text": "Goutweed\\nMust have completed Eadgar's Ruse", + "level": 29 + }, + { + "item": "rs:ranarr_weed", + "text": "Ranarr weed", + "level": 32 + }, + { + "item": "rs:toadflax", + "text": "Toadflax", + "level": 38 + }, + { + "item": "rs:avantoe", + "text": "Avantoe", + "level": 50 + }, + { + "item": "rs:kwuarm", + "text": "Kwuarm", + "level": 56 + }, + { + "item": "rs:snapdragon", + "text": "Snapdragon", + "level": 62 + }, + { + "item": "rs:cadantine", + "text": "Cadantine", + "level": 67 + }, + { + "item": "rs:lantadyme", + "text": "Lantadyme", + "level": 73 + }, + { + "item": "rs:dwarf_weed", + "text": "Dwarf weed", + "level": 79 + }, + { + "item": "rs:torstol", + "text": "Torstol", + "level": 85 + } + ] + }, + { + "name": "special", + "lines": [ + { + "item": "rs:teak_trees", + "text": "Teak trees\\nPayment: Limpwurt root x15", + "level": 35 + }, + { + "item": "rs:grapes", + "text": "Grapes", + "level": 36 + }, + { + "item": "rs:bittercap_mushrooms", + "text": "Bittercap mushrooms", + "level": 53 + }, + { + "item": "rs:mahogany_trees", + "text": "Mahogany trees\\nPayment: yanillian hops x25", + "level": 55 + }, + { + "item": "rs:cacti", + "text": "Cacti\\nPayment: Cadava berries x6", + "level": 55 + }, + { + "item": "rs:belladonna", + "text": "Belladonna", + "level": 63 + }, + { + "item": "rs:potato_cacti", + "text": "Potato cacti", + "level": 64 + }, + { + "item": "rs:hespori", + "text": "Hespori", + "level": 65 + }, + { + "item": "rs:calquat_trees", + "text": "Calquat trees\\nPayment: Poison ivy Berries x8", + "level": 72 + } + ] + }, + { + "name": "Multiple roots", + "lines": [ + { + "item": "rs:oak_roots", + "text": "2x oak roots", + "level": 23 + }, + { + "item": "rs:oak_roots", + "text": "3x oak roots", + "level": 31 + }, + { + "item": "rs:willow_roots", + "text": "2x willow roots", + "level": 38 + }, + { + "item": "rs:oak_roots", + "text": "4x oak roots", + "level": 39 + }, + { + "item": "rs:willow_roots", + "text": "3x willow roots", + "level": 46 + }, + { + "item": "rs:mapple_roots", + "text": "2x mapple roots", + "level": 53 + }, + { + "item": "rs:willow_roots", + "text": "4x willow roots", + "level": 54 + }, + { + "item": "rs:maple_roots", + "text": "3x mapple roots", + "level": 61 + }, + { + "item": "rs:yew_roots", + "text": "2x yew roots", + "level": 68 + }, + { + "item": "rs:maple_roots", + "text": "4x mapple roots", + "level": 69 + }, + { + "item": "rs:yew_roots", + "text": "3x yew roots", + "level": 76 + }, + { + "item": "rs:magic_roots", + "text": "2x magic roots", + "level": 83 + }, + { + "item": "rs:yew_roots", + "text": "4x yew roots", + "level": 84 + }, + { + "item": "rs:magic_roots", + "text": "3x magic roots", + "level": 91 + }, + { + "item": "rs:magic_roots", + "text": "4x magic roots", + "level": 99 + } + ] + } ] - },{ - "name": "Bushes", - "lines": [ - { - "item": "rs:redberry_bushes", - "text": "Redberry bushes\\nPayment: Cabbages(10) x4", - "level": 10 - }, - { - "item": "rs:cadavaberry_bushes", - "text": "Cadavanerry bushes\\nPayment: Tomatoes(5) x3", - "level": 22 - }, - { - "item": "rs:dwellberry_bushes", - "text": "Dwellberry bushes\\nPayment: Strawberries(5) x3", - "level": 36 - }, - { - "item": "rs:jangerberry_bushes", - "text": "Jangerberry bushes\\nPayment: Watermelon x6", - "level": 48 - }, - { - "item": "rs:white_berry_bushes", - "text": "White berry bushes\\nPayment: Mushroom x8", - "level": 59 - }, - { - "item": "rs:poison_ivy_bushes", - "text": "Poison ivy bushes", - "level": 70 - } - ] - },{ - "name": "Flowers", - "lines": [ - { - "item": "rs:marigolds", - "text": "Marigolds\\nProtects onions, tomatoes and potatoes", - "level": 2 - }, - { - "item": "rs:rosemary", - "text": "Rosemary\\nProtects cabbages from disease", - "level": 22 - }, - { - "item": "scarecrow", - "text": "Make and place a scarecrow\\nProtects sweetcorn from birds", - "level": 23 - }, - { - "item": "rs:nasturtiums", - "text": "Nasturtiums\\nProtects watermelons from disease", - "level": 24 - }, - { - "item": "rs:woad", - "text": "Woad", - "level": 25 - }, - { - "item": "rs:limpwurt_root", - "text": "Limpwurt plants", - "level": 26 - }, - { - "item": "rs:white_lily", - "text": "White lily\\nProtects all allotment crops", - "level": 58 - } - ] - },{ - "name": "Herbs", - "lines": [ - { - "item": "rs:guam_leaf", - "text": "Guam leaf", - "level": 9 - }, - { - "item": "rs:marrentill", - "text": "Marrentill", - "level": 14 - }, - { - "item": "tarromin", - "text": "Tarromin", - "level": 19 - }, - { - "item": "rs:harralander", - "text": "Harralander", - "level": 26 - }, - { - "item": "rs:goutweed", - "text": "Goutweed\\nMust have completed Eadgar's Ruse", - "level": 29 - }, - { - "item": "rs:ranarr_weed", - "text": "Ranarr weed", - "level": 32 - }, - { - "item": "rs:toadflax", - "text": "Toadflax", - "level": 38 - }, - { - "item": "rs:avantoe", - "text": "Avantoe", - "level": 50 - }, - { - "item": "rs:kwuarm", - "text": "Kwuarm", - "level": 56 - }, - { - "item": "rs:snapdragon", - "text": "Snapdragon", - "level": 62 - }, - { - "item": "rs:cadantine", - "text": "Cadantine", - "level": 67 - }, - { - "item": "rs:lantadyme", - "text": "Lantadyme", - "level": 73 - }, - { - "item": "rs:dwarf_weed", - "text": "Dwarf weed", - "level": 79 - }, - { - "item": "rs:torstol", - "text": "Torstol", - "level": 85 - } - ] - },{ - "name": "special", - "lines": [ - { - "item": "rs:teak_trees", - "text": "Teak trees\\nPayment: Limpwurt root x15", - "level": 35 - }, - { - "item": "rs:grapes", - "text": "Grapes", - "level": 36 - }, - { - "item": "rs:bittercap_mushrooms", - "text": "Bittercap mushrooms", - "level": 53 - }, - { - "item": "rs:mahogany_trees", - "text": "Mahogany trees\\nPayment: yanillian hops x25", - "level": 55 - }, - { - "item": "rs:cacti", - "text": "Cacti\\nPayment: Cadava berries x6", - "level": 55 - }, { - "item": "rs:belladonna", - "text": "Belladonna", - "level": 63 - }, - { - "item": "rs:potato_cacti", - "text": "Potato cacti", - "level": 64 - }, - { - "item": "rs:hespori", - "text": "Hespori", - "level": 65 - }, - { - "item": "rs:calquat_trees", - "text": "Calquat trees\\nPayment: Poison ivy Berries x8", - "level": 72 - } - ] - },{ - "name": "Multiple roots", - "lines": [ - { - "item": "rs:oak_roots", - "text": "2x oak roots", - "level": 23 - }, - { - "item": "rs:oak_roots", - "text": "3x oak roots", - "level": 31 - }, - { - "item": "rs:willow_roots", - "text": "2x willow roots", - "level": 38 - }, - { - "item": "rs:oak_roots", - "text": "4x oak roots", - "level": 39 - }, - { - "item": "rs:willow_roots", - "text": "3x willow roots", - "level": 46 - }, { - "item": "rs:mapple_roots", - "text": "2x mapple roots", - "level": 53 - }, - { - "item": "rs:willow_roots", - "text": "4x willow roots", - "level": 54 - }, - { - "item": "rs:maple_roots", - "text": "3x mapple roots", - "level": 61 - }, - { - "item": "rs:yew_roots", - "text": "2x yew roots", - "level": 68 - }, - { - "item": "rs:maple_roots", - "text": "4x mapple roots", - "level": 69 - }, - { - "item": "rs:yew_roots", - "text": "3x yew roots", - "level": 76 - }, - { - "item": "rs:magic_roots", - "text": "2x magic roots", - "level": 83 - }, - { - "item": "rs:yew_roots", - "text": "4x yew roots", - "level": 84 - }, - { - "item": "rs:magic_roots", - "text": "3x magic roots", - "level": 91 - }, - { - "item": "rs:magic_roots", - "text": "4x magic roots", - "level": 99 - } - ] - } -] -} \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/firemaking.json b/src/plugins/skills/skill-guides/firemaking.json index 027cf7643..f4a3f6f1f 100644 --- a/src/plugins/skills/skill-guides/firemaking.json +++ b/src/plugins/skills/skill-guides/firemaking.json @@ -1,232 +1,232 @@ { - "id": 132, - "name": "Firemaking", - "members": false, - "sub_guides": [ - { - "name": "Burning", - "lines": [ - { - "item": "rs:logs", - "text": "Normal logs", - "level": 1 - }, - { - "item": "rs:achey_logs", - "text": "Members: Achey logs", - "level": 1 - }, - { - "item": "rs:pyre_logs", - "text": "Members: Pyre logs", - "level": 5 - }, - { - "item": "rs:oak_logs", - "text": "Oak logs", - "level": 15 - }, - { - "item": "rs:oak_pyre_logs", - "text": "Members: Oak pyre logs", - "level": 20 - }, - { - "item": "rs:willow_logs", - "text": "Willow logs", - "level": 30 - }, - { - "item": "rs:teak_logs", - "text": "Members: Teak logs", - "level": 35 - }, - { - "item": "rs:willow_pyre_logs", - "text": "Members: Willow pyre logs", - "level": 35 - }, - { - "item": "rs:teak_pyre_logs", - "text": "Members: Teak pyre logs", - "level": 40 - }, - { - "item": "rs:maple_logs", - "text": "Maple logs", - "level": 45 - }, - { - "item": "rs:mahogany_logs", - "text": "Members: Mahogany logs", - "level": 50 - }, - { - "item": "rs:maple_pyre_logs", - "text": "Members: Maple pyre logs", - "level": 50 - }, - { - "item": "rs:mahogany_pyre_logs", - "text": "Members: Mahogany pyre logs", - "level": 55 - }, - { - "item": "rs:yew_logs", - "text": "Yew logs", - "level": 60 - }, - { - "item": "rs:yew_pyre_logs", - "text": "Members: Yew pyre logs", - "level": 65 - }, - { - "item": "rs:magic_logs", - "text": "Members: Magic logs", - "level": 75 - }, - { - "item": "rs:magic_pyre_logs", - "text": "Members: Magic pyre logs", - "level": 80 - } - ] - }, - { - "name": "Barbarian", - "lines": [ - { - "item": "rs:normal_pyre_ships", - "text": "Normal Pyre Ships (with 11 Crafting)", - "level": 11 - }, - { - "item": "rs:normal_logs", - "text": "Normal Logs", - "level": 21 - }, - { - "item": "rs:achey_logs", - "text": "Achey Logs", - "level": 21 - }, - { - "item": "rs:oak_pyre_ships", - "text": "Oak Pyre Ships (with 25 Crafting)", - "level": 25 - }, - { - "item": "rs:oak_logs", - "text": "Oak Logs", - "level": 35 - }, - { - "item": "rs:willow_pyre_ships", - "text": "Willow Pyre Ships (with 40 Crafting)", - "level": 40 - }, - { - "item": "rs:teak_pyre_ships", - "text": "Teak Pyre Ships (with 45 Crafting)", - "level": 45 - }, - { - "item": "rs:willow_logs", - "text": "Willow Logs", - "level": 50 - }, - { - "item": "rs:teak_logs", - "text": "Teak Logs", - "level": 55 - }, - { - "item": "rs:maple_pyre_ships", - "text": "Maple Pyre Ships (with 55 Crafting)", - "level": 55 - }, - { - "item": "rs:mahogany_pyre_ships", - "text": "Mahogany Pyre Ships (with 60 Crafting)", - "level": 60 - }, - { - "item": "rs:maple_logs", - "text": "Maple Logs", - "level": 65 - }, - { - "item": "rs:yew_pyre_ships", - "text": "Yew Pyre Ships (with 70 Crafting)", - "level": 70 - }, - { - "item": "rs:mahogany_logs", - "text": "Mahogany Logs", - "level": 70 - }, - { - "item": "rs:yew_logs", - "text": "Yew Logs", - "level": 80 - }, - { - "item": "rs:magic_pyre_ships", - "text": "Magic Pyre Ships", - "level": 85 - }, - { - "item": "rs:magic_logs", - "text": "Magic Logs", - "level": 95 - } - ] - }, - { - "name": "Equipment", - "lines": [ - { - "item": "rs:candle", - "text": "Candle", - "level": 1 - }, - { - "item": "rs:candle_lanterns", - "text": "Candle lanterns", - "level": 4 - }, - { - "item": "rs:oil_lamps", - "text": "Oil lamps", - "level": 12 - }, - { - "item": "rs:iron_spits", - "text": "Members: Iron spits", - "level": 20 - }, - { - "item": "rs:oil_lanterns", - "text": "Oil lanterns", - "level": 26 - }, - { - "item": "rs:harpie_bug_lanterns", - "text": "Harpie bug lanterns (not a light source)", - "level": 33 - }, - { - "item": "rs:bullseye_lanterns", - "text": "Bullseye lanterns", - "level": 49 - }, - { - "item": "rs:sapphire_lanterns", - "text": "Sapphire lanterns", - "level": 49 + "id": 132, + "name": "Firemaking", + "members": false, + "sub_guides": [ + { + "name": "Burning", + "lines": [ + { + "item": "rs:logs", + "text": "Normal logs", + "level": 1 + }, + { + "item": "rs:achey_logs", + "text": "Members: Achey logs", + "level": 1 + }, + { + "item": "rs:pyre_logs", + "text": "Members: Pyre logs", + "level": 5 + }, + { + "item": "rs:oak_logs", + "text": "Oak logs", + "level": 15 + }, + { + "item": "rs:oak_pyre_logs", + "text": "Members: Oak pyre logs", + "level": 20 + }, + { + "item": "rs:willow_logs", + "text": "Willow logs", + "level": 30 + }, + { + "item": "rs:teak_logs", + "text": "Members: Teak logs", + "level": 35 + }, + { + "item": "rs:willow_pyre_logs", + "text": "Members: Willow pyre logs", + "level": 35 + }, + { + "item": "rs:teak_pyre_logs", + "text": "Members: Teak pyre logs", + "level": 40 + }, + { + "item": "rs:maple_logs", + "text": "Maple logs", + "level": 45 + }, + { + "item": "rs:mahogany_logs", + "text": "Members: Mahogany logs", + "level": 50 + }, + { + "item": "rs:maple_pyre_logs", + "text": "Members: Maple pyre logs", + "level": 50 + }, + { + "item": "rs:mahogany_pyre_logs", + "text": "Members: Mahogany pyre logs", + "level": 55 + }, + { + "item": "rs:yew_logs", + "text": "Yew logs", + "level": 60 + }, + { + "item": "rs:yew_pyre_logs", + "text": "Members: Yew pyre logs", + "level": 65 + }, + { + "item": "rs:magic_logs", + "text": "Members: Magic logs", + "level": 75 + }, + { + "item": "rs:magic_pyre_logs", + "text": "Members: Magic pyre logs", + "level": 80 + } + ] + }, + { + "name": "Barbarian", + "lines": [ + { + "item": "rs:normal_pyre_ships", + "text": "Normal Pyre Ships (with 11 Crafting)", + "level": 11 + }, + { + "item": "rs:normal_logs", + "text": "Normal Logs", + "level": 21 + }, + { + "item": "rs:achey_logs", + "text": "Achey Logs", + "level": 21 + }, + { + "item": "rs:oak_pyre_ships", + "text": "Oak Pyre Ships (with 25 Crafting)", + "level": 25 + }, + { + "item": "rs:oak_logs", + "text": "Oak Logs", + "level": 35 + }, + { + "item": "rs:willow_pyre_ships", + "text": "Willow Pyre Ships (with 40 Crafting)", + "level": 40 + }, + { + "item": "rs:teak_pyre_ships", + "text": "Teak Pyre Ships (with 45 Crafting)", + "level": 45 + }, + { + "item": "rs:willow_logs", + "text": "Willow Logs", + "level": 50 + }, + { + "item": "rs:teak_logs", + "text": "Teak Logs", + "level": 55 + }, + { + "item": "rs:maple_pyre_ships", + "text": "Maple Pyre Ships (with 55 Crafting)", + "level": 55 + }, + { + "item": "rs:mahogany_pyre_ships", + "text": "Mahogany Pyre Ships (with 60 Crafting)", + "level": 60 + }, + { + "item": "rs:maple_logs", + "text": "Maple Logs", + "level": 65 + }, + { + "item": "rs:yew_pyre_ships", + "text": "Yew Pyre Ships (with 70 Crafting)", + "level": 70 + }, + { + "item": "rs:mahogany_logs", + "text": "Mahogany Logs", + "level": 70 + }, + { + "item": "rs:yew_logs", + "text": "Yew Logs", + "level": 80 + }, + { + "item": "rs:magic_pyre_ships", + "text": "Magic Pyre Ships", + "level": 85 + }, + { + "item": "rs:magic_logs", + "text": "Magic Logs", + "level": 95 + } + ] + }, + { + "name": "Equipment", + "lines": [ + { + "item": "rs:candle", + "text": "Candle", + "level": 1 + }, + { + "item": "rs:candle_lanterns", + "text": "Candle lanterns", + "level": 4 + }, + { + "item": "rs:oil_lamps", + "text": "Oil lamps", + "level": 12 + }, + { + "item": "rs:iron_spits", + "text": "Members: Iron spits", + "level": 20 + }, + { + "item": "rs:oil_lanterns", + "text": "Oil lanterns", + "level": 26 + }, + { + "item": "rs:harpie_bug_lanterns", + "text": "Harpie bug lanterns (not a light source)", + "level": 33 + }, + { + "item": "rs:bullseye_lanterns", + "text": "Bullseye lanterns", + "level": 49 + }, + { + "item": "rs:sapphire_lanterns", + "text": "Sapphire lanterns", + "level": 49 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/fishing.json b/src/plugins/skills/skill-guides/fishing.json index 0f42f5820..74ddf7b39 100644 --- a/src/plugins/skills/skill-guides/fishing.json +++ b/src/plugins/skills/skill-guides/fishing.json @@ -1,167 +1,167 @@ { - "id": 126, - "name": "Fishing", - "members": false, - "sub_guides": [ - { - "name": "Catching", - "lines": [ - { - "item": "rs:raw_shrimp", - "text": "Raw Shrimp", - "level": 1 - }, - { - "item": "rs:raw_sardine", - "text": "Raw Sardine", - "level": 5 - }, - { - "item": "rs:raw_karambwanji", - "text": "Members: Raw Karambwanji", - "level": 5 - }, - { - "item": "rs:raw_herring", - "text": "Raw Herring", - "level": 10 - }, - { - "item": "rs:raw_anchovies", - "text": "Raw Anchovies", - "level": 15 - }, - { - "item": "rs:raw_mackerel", - "text": "Members: Raw Mackerel", - "level": 16 - }, - { - "item": "rs:raw_trout", - "text": "Raw Trout", - "level": 20 - }, - { - "item": "rs:raw_cod", - "text": "Members: Raw Cod", - "level": 23 - }, - { - "item": "rs:raw_pike", - "text": "Raw Pike", - "level": 25 - }, - { - "item": "rs:raw_slimy_eel", - "text": "Members: Raw Slimy Eel", - "level": 28 - }, - { - "item": "rs:raw_salmon", - "text": "Raw Salmon", - "level": 30 - }, - { - "item": "rs:raw_tuna", - "text": "Raw Tuna", - "level": 35 - }, - { - "item": "rs:raw_cave_eel", - "text": "Members: Raw Cave Eel", - "level": 38 - }, - { - "item": "rs:raw_lobster", - "text": "Raw Lobster", - "level": 40 - }, - { - "item": "rs:raw_bass", - "text": "Members: Raw Bass", - "level": 46 - }, - { - "item": "rs:raw_swordfish", - "text": "Raw Swordfish", - "level": 50 - }, - { - "item": "rs:raw_lava_eel", - "text": "Members: Raw Lava Eel", - "level": 53 - }, - { - "item": "rs:raw_monkfish", - "text": "Members: Raw Monkfish", - "level": 62 - }, - { - "item": "rs:raw_karambwan", - "text": "Members: Raw Karambwan", - "level": 65 - }, - { - "item": "rs:raw_shark", - "text": "Raw Shark", - "level": 76 - }, - { - "item": "rs:raw_sea_turtle", - "text": "Raw Sea Turtle", - "level": 79 - }, - { - "item": "rs:raw_manta_ray", - "text": "Raw Manta Ray", - "level": 81 - } - ] - }, - { - "name": "Equipment", - "lines": [ - { - "item": "rs:small_fishing_net", - "text": "Small Fishing Net", - "level": 1 - }, - { - "item": "rs:fishing_rod", - "text": "Fishing Rod", - "level": 5 - }, - { - "item": "rs:big_fishing_net", - "text": "Big Fishing Net", - "level": 16 - }, - { - "item": "rs:fly_fishing_rod", - "text": "Members: Fly Fishing Rod", - "level": 20 - }, - { - "item": "rs:harpoon", - "text": "harpoon", - "level": 35 - }, - { - "item": "rs:lobster_pot", - "text": "Lobster_Pot", - "level": 40 - }, - { - "item": "rs:oily_fishing_rod", - "text": "Oily Fishing Rod", - "level": 53 - }, - { - "item": "rs:karambwan_vessel", - "text": "Karambwan Vessel", - "level": 65 + "id": 126, + "name": "Fishing", + "members": false, + "sub_guides": [ + { + "name": "Catching", + "lines": [ + { + "item": "rs:raw_shrimp", + "text": "Raw Shrimp", + "level": 1 + }, + { + "item": "rs:raw_sardine", + "text": "Raw Sardine", + "level": 5 + }, + { + "item": "rs:raw_karambwanji", + "text": "Members: Raw Karambwanji", + "level": 5 + }, + { + "item": "rs:raw_herring", + "text": "Raw Herring", + "level": 10 + }, + { + "item": "rs:raw_anchovies", + "text": "Raw Anchovies", + "level": 15 + }, + { + "item": "rs:raw_mackerel", + "text": "Members: Raw Mackerel", + "level": 16 + }, + { + "item": "rs:raw_trout", + "text": "Raw Trout", + "level": 20 + }, + { + "item": "rs:raw_cod", + "text": "Members: Raw Cod", + "level": 23 + }, + { + "item": "rs:raw_pike", + "text": "Raw Pike", + "level": 25 + }, + { + "item": "rs:raw_slimy_eel", + "text": "Members: Raw Slimy Eel", + "level": 28 + }, + { + "item": "rs:raw_salmon", + "text": "Raw Salmon", + "level": 30 + }, + { + "item": "rs:raw_tuna", + "text": "Raw Tuna", + "level": 35 + }, + { + "item": "rs:raw_cave_eel", + "text": "Members: Raw Cave Eel", + "level": 38 + }, + { + "item": "rs:raw_lobster", + "text": "Raw Lobster", + "level": 40 + }, + { + "item": "rs:raw_bass", + "text": "Members: Raw Bass", + "level": 46 + }, + { + "item": "rs:raw_swordfish", + "text": "Raw Swordfish", + "level": 50 + }, + { + "item": "rs:raw_lava_eel", + "text": "Members: Raw Lava Eel", + "level": 53 + }, + { + "item": "rs:raw_monkfish", + "text": "Members: Raw Monkfish", + "level": 62 + }, + { + "item": "rs:raw_karambwan", + "text": "Members: Raw Karambwan", + "level": 65 + }, + { + "item": "rs:raw_shark", + "text": "Raw Shark", + "level": 76 + }, + { + "item": "rs:raw_sea_turtle", + "text": "Raw Sea Turtle", + "level": 79 + }, + { + "item": "rs:raw_manta_ray", + "text": "Raw Manta Ray", + "level": 81 + } + ] + }, + { + "name": "Equipment", + "lines": [ + { + "item": "rs:small_fishing_net", + "text": "Small Fishing Net", + "level": 1 + }, + { + "item": "rs:fishing_rod", + "text": "Fishing Rod", + "level": 5 + }, + { + "item": "rs:big_fishing_net", + "text": "Big Fishing Net", + "level": 16 + }, + { + "item": "rs:fly_fishing_rod", + "text": "Members: Fly Fishing Rod", + "level": 20 + }, + { + "item": "rs:harpoon", + "text": "harpoon", + "level": 35 + }, + { + "item": "rs:lobster_pot", + "text": "Lobster_Pot", + "level": 40 + }, + { + "item": "rs:oily_fishing_rod", + "text": "Oily Fishing Rod", + "level": 53 + }, + { + "item": "rs:karambwan_vessel", + "text": "Karambwan Vessel", + "level": 65 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/herblore.json b/src/plugins/skills/skill-guides/herblore.json index cbc66d74a..217861cce 100644 --- a/src/plugins/skills/skill-guides/herblore.json +++ b/src/plugins/skills/skill-guides/herblore.json @@ -3,241 +3,240 @@ "name": "Herblore", "members": true, "sub_guides": [ - { - "name": "Potions", - "lines": [ - { - "item": "rs:herblore_attack_potion", - "text": "Attack potion\\nGuam leaf & eye of newt", - "level": 3 - }, - { - "item": "rs:herblore_anti_poison_potion", - "text": "Anti-poison potion\\nMarrentil & ground unicorn horn", - "level": 5 - }, - { - "item": "rs:herblore_relicyms_balm", - "text": "Relicym's balm", - "level": 8 - }, - { - "item": "rs:herblore_strength_potion", - "text": "Strength potion\\nTarromin & limpwurt root", - "level": 12 - }, - { - "item": "rs:herblore_serum_207", - "text": "Serum 207\\nTarromin & ashes", - "level": 15 - }, - { - "item": "rs:herblore_stat_restore_potion", - "text": "Stat restore potion\\nHarralander & red spiders' eggs", - "level": 22 - }, - { - "item": "rs:guthix_balance_potion", - "text": "Guthix balance potion", - "level": 22 - }, - { - "item": "rs:herblore_energy_potion", - "text": "Energy potion\\nHarralander & chocolate dust", - "level": 26 - }, - { - "item": "rs:herblore_defence_potion", - "text": "Defence potion\\nRanarr weed & white berries", - "level": 30 - }, - { - "item": "rs:herblore_combat_potion", - "text": "Combat potion\\nHarralander & ground desert goat horn", - "level": 36 - }, - { - "item": "rs:herblore_prayer_restore_potion", - "text": "Prayer restore potion\\nRanarr weed & snape grass", - "level": 38 - }, - { - "item": "rs:herblore_super_attack_potion", - "text": "Super attack potion\\nIrit leaf & eye of newt", - "level": 45 - }, - { - "item": "rs:herblore_super_anti_poison_potion", - "text": "Super anti-poison potion\\nIrit leaf & ground unicorn horn", - "level": 48 - }, - { - "item": "rs:herblore_fishing_potion", - "text": "Fishing potion\\nAvantoe & snape grass", - "level": 50 - }, - { - "item": "rs:herblore_super_energy_potion", - "text": "Super energy potion\\nAvantoe & Mort Myre fungi", - "level": 52 - }, - { - "item": "rs:herblore_hunting_potion", - "text": "Hunting potion - Avantoe & ground\\nsabre-toothed kebbit teeth", - "level": 53 - }, - { - "item": "rs:herblore_super_strength_potion", - "text": "Super strength potion\\nKwuarm & limpwurt root", - "level": 55 - }, - { - "item": "rs:herblore_magic_essence_potion", - "text": "Magic essence potion\\nStar flower & ground gorak's claw", - "level": 57 - }, - { - "item": "rs:herblore_weapon_poison", - "text": "Weapon Poison\\nKwuarm & ground blue dragon scale", - "level": 60 - }, - { - "item": "rs:herblore_super_defence_potion", - "text": "Super defence potion\\nCadantine & white berries", - "level": 66 - }, - { - "item": "rs:herblore_antidote_plus", - "text": "Antidote+\\nCoconut milk, toadflax & yew roots", - "level": 68 - }, - { - "item": "rs:herblore_anti_firebreath_potion", - "text": "Anti-firebreath potion\\nLantadyme & ground blue dragon scale", - "level": 69 - }, - { - "item": "rs:herblore_ranging_potion", - "text": "Ranging potion\\nDwarf weed & wine of Zamorak", - "level": 72 - }, - { - "item": "rs:herblore_weapon_poison_plus", - "text": "Weapon poison(+)\\nCoconut milk, cactus spine & red spiders' eggs", - "level": 73 - }, - { - "item": "rs:herblore_magic_potion", - "text": "Magic potion\\nLantadyme & potato cactus", - "level": 76 - }, - { - "item": "rs:herblore_zamorak_brew", - "text": "Zamorak brew\\nTorstol & jangerberries", - "level": 78 - }, - { - "item": "rs:herblore_antidote_plus_plus", - "text": "Antidote++\\nCoconut milk, irit leaf & magic tree roots", - "level": 79 - }, - { - "item": "rs:herblore_saradomin_brew", - "text": "Saradomin brew\\nToadflax & crushed birdnest", - "level": 81 - }, - { - "item": "rs:herblore_weapon_poison_plus_plus", - "text": "Weapon poison(++)\\nCoconut milk, nightshade & poison ivy berries", - "level": 82 - } - ] - }, - { - "name": "Herbs", - "lines": [ - { - "item": "rs:guam_leaf", - "text": "Guam leaf", - "level": 3 - }, - { - "item": "rs:rogues_purse", - "text": "Rogue's purse", - "level": 3 - }, - { - "item": "rs:snake_weed", - "text": "Snake weed", - "level": 3 - }, - { - "item": "rs:marrentill", - "text": "Marrentill", - "level": 5 - }, - { - "item": "rs:tarromin", - "text": "Tarromin", - "level": 11 - }, - { - "item": "rs:harralander", - "text": "Harralander", - "level": 20 - }, - { - "item": "rs:ranarr_weed", - "text": "Ranarr weed", - "level": 25 - }, - { - "item": "rs:toadflax", - "text": "Toadflax", - "level": 30 - }, - { - "item": "rs:irit_leaf", - "text": "Irit leaf", - "level": 40 - }, - { - "item": "rs:avantoe", - "text": "Avantoe", - "level": 48 - }, - { - "item": "rs:kwuarm", - "text": "Kwuarm", - "level": 54 - }, - { - "item": "rs:snapdragon", - "text": "Snapdragon", - "level": 59 - }, - { - "item": "rs:cadantine", - "text": "Cadantine", - "level": 65 - }, - { - "item": "rs:lantadyme", - "text": "Lantadyme", - "level": 67 - }, - { - "item": "rs:dwarf_weed", - "text": "Dwarf weed", - "level": 70 - }, - { - "item": "rs:torstol", - "text": "Torstol", - "level": 75 - } - ] - } + { + "name": "Potions", + "lines": [ + { + "item": "rs:herblore_attack_potion", + "text": "Attack potion\\nGuam leaf & eye of newt", + "level": 3 + }, + { + "item": "rs:herblore_anti_poison_potion", + "text": "Anti-poison potion\\nMarrentil & ground unicorn horn", + "level": 5 + }, + { + "item": "rs:herblore_relicyms_balm", + "text": "Relicym's balm", + "level": 8 + }, + { + "item": "rs:herblore_strength_potion", + "text": "Strength potion\\nTarromin & limpwurt root", + "level": 12 + }, + { + "item": "rs:herblore_serum_207", + "text": "Serum 207\\nTarromin & ashes", + "level": 15 + }, + { + "item": "rs:herblore_stat_restore_potion", + "text": "Stat restore potion\\nHarralander & red spiders' eggs", + "level": 22 + }, + { + "item": "rs:guthix_balance_potion", + "text": "Guthix balance potion", + "level": 22 + }, + { + "item": "rs:herblore_energy_potion", + "text": "Energy potion\\nHarralander & chocolate dust", + "level": 26 + }, + { + "item": "rs:herblore_defence_potion", + "text": "Defence potion\\nRanarr weed & white berries", + "level": 30 + }, + { + "item": "rs:herblore_combat_potion", + "text": "Combat potion\\nHarralander & ground desert goat horn", + "level": 36 + }, + { + "item": "rs:herblore_prayer_restore_potion", + "text": "Prayer restore potion\\nRanarr weed & snape grass", + "level": 38 + }, + { + "item": "rs:herblore_super_attack_potion", + "text": "Super attack potion\\nIrit leaf & eye of newt", + "level": 45 + }, + { + "item": "rs:herblore_super_anti_poison_potion", + "text": "Super anti-poison potion\\nIrit leaf & ground unicorn horn", + "level": 48 + }, + { + "item": "rs:herblore_fishing_potion", + "text": "Fishing potion\\nAvantoe & snape grass", + "level": 50 + }, + { + "item": "rs:herblore_super_energy_potion", + "text": "Super energy potion\\nAvantoe & Mort Myre fungi", + "level": 52 + }, + { + "item": "rs:herblore_hunting_potion", + "text": "Hunting potion - Avantoe & ground\\nsabre-toothed kebbit teeth", + "level": 53 + }, + { + "item": "rs:herblore_super_strength_potion", + "text": "Super strength potion\\nKwuarm & limpwurt root", + "level": 55 + }, + { + "item": "rs:herblore_magic_essence_potion", + "text": "Magic essence potion\\nStar flower & ground gorak's claw", + "level": 57 + }, + { + "item": "rs:herblore_weapon_poison", + "text": "Weapon Poison\\nKwuarm & ground blue dragon scale", + "level": 60 + }, + { + "item": "rs:herblore_super_defence_potion", + "text": "Super defence potion\\nCadantine & white berries", + "level": 66 + }, + { + "item": "rs:herblore_antidote_plus", + "text": "Antidote+\\nCoconut milk, toadflax & yew roots", + "level": 68 + }, + { + "item": "rs:herblore_anti_firebreath_potion", + "text": "Anti-firebreath potion\\nLantadyme & ground blue dragon scale", + "level": 69 + }, + { + "item": "rs:herblore_ranging_potion", + "text": "Ranging potion\\nDwarf weed & wine of Zamorak", + "level": 72 + }, + { + "item": "rs:herblore_weapon_poison_plus", + "text": "Weapon poison(+)\\nCoconut milk, cactus spine & red spiders' eggs", + "level": 73 + }, + { + "item": "rs:herblore_magic_potion", + "text": "Magic potion\\nLantadyme & potato cactus", + "level": 76 + }, + { + "item": "rs:herblore_zamorak_brew", + "text": "Zamorak brew\\nTorstol & jangerberries", + "level": 78 + }, + { + "item": "rs:herblore_antidote_plus_plus", + "text": "Antidote++\\nCoconut milk, irit leaf & magic tree roots", + "level": 79 + }, + { + "item": "rs:herblore_saradomin_brew", + "text": "Saradomin brew\\nToadflax & crushed birdnest", + "level": 81 + }, + { + "item": "rs:herblore_weapon_poison_plus_plus", + "text": "Weapon poison(++)\\nCoconut milk, nightshade & poison ivy berries", + "level": 82 + } + ] + }, + { + "name": "Herbs", + "lines": [ + { + "item": "rs:guam_leaf", + "text": "Guam leaf", + "level": 3 + }, + { + "item": "rs:rogues_purse", + "text": "Rogue's purse", + "level": 3 + }, + { + "item": "rs:snake_weed", + "text": "Snake weed", + "level": 3 + }, + { + "item": "rs:marrentill", + "text": "Marrentill", + "level": 5 + }, + { + "item": "rs:tarromin", + "text": "Tarromin", + "level": 11 + }, + { + "item": "rs:harralander", + "text": "Harralander", + "level": 20 + }, + { + "item": "rs:ranarr_weed", + "text": "Ranarr weed", + "level": 25 + }, + { + "item": "rs:toadflax", + "text": "Toadflax", + "level": 30 + }, + { + "item": "rs:irit_leaf", + "text": "Irit leaf", + "level": 40 + }, + { + "item": "rs:avantoe", + "text": "Avantoe", + "level": 48 + }, + { + "item": "rs:kwuarm", + "text": "Kwuarm", + "level": 54 + }, + { + "item": "rs:snapdragon", + "text": "Snapdragon", + "level": 59 + }, + { + "item": "rs:cadantine", + "text": "Cadantine", + "level": 65 + }, + { + "item": "rs:lantadyme", + "text": "Lantadyme", + "level": 67 + }, + { + "item": "rs:dwarf_weed", + "text": "Dwarf weed", + "level": 70 + }, + { + "item": "rs:torstol", + "text": "Torstol", + "level": 75 + } + ] + } ] - } - \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/hitpoint.json b/src/plugins/skills/skill-guides/hitpoint.json index 0eda07238..b6698647e 100644 --- a/src/plugins/skills/skill-guides/hitpoint.json +++ b/src/plugins/skills/skill-guides/hitpoint.json @@ -6,291 +6,291 @@ { "name": "Hitpoints", "lines": [ - { - "text": "Hitpoints are used to tell you how healthy\\n your character is. A character who reaches\\n0 Hitpoints has died, but will reappear in\\ntheir chosen respawn location(normally Lumbridge).\\n\\nIf you see any red 'hit splash' during combat\\n, the number shown corresponds to the number\\n of Hitpoints lost as a result of that strike.\\n\\nBlue hit splash means no damage has been dealt.\\n\\nGreen hit splash are poison damage.", - "level": "" - } + { + "text": "Hitpoints are used to tell you how healthy\\n your character is. A character who reaches\\n0 Hitpoints has died, but will reappear in\\ntheir chosen respawn location(normally Lumbridge).\\n\\nIf you see any red 'hit splash' during combat\\n, the number shown corresponds to the number\\n of Hitpoints lost as a result of that strike.\\n\\nBlue hit splash means no damage has been dealt.\\n\\nGreen hit splash are poison damage.", + "level": "" + } ] - },{ - "name": "Healing", - "lines": [ - { - "item": "rs:purple_sweets", - "text": "Purple Sweets: Restores 1-3 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:anchovies", - "text": "Anchovies: Restores 1 Hitpoint", - "level": "" - }, - { - "item": "rs:shrimp", - "text": "Shrimp: Restores 3 Hitpoints", - "level": "" - }, - { - "item": "rs:cooked_chicken", - "text": "Cooked chicken: Restores 3 Hitpoints", - "level": "" - }, - { - "item": "rs:sardine", - "text": "Sardine: Restores 3 Hitpoints", - "level": "" - }, - { - "item": "rs:cooked_meat", - "text": "Cooked meat: Restores 3 Hitpoints", - "level": "" - }, - { - "item": "rs:bread", - "text": "Bread: Restores 5 Hitpoints", - "level": "" - }, - { - "item": "rs:bread", - "text": "Bread: Restores 5 Hitpoints", - "level": "" - }, - { - "item": "rs:herring", - "text": "Herring: Restores 5 Hitpoints", - "level": "" - }, - { - "item": "rs:cooked_rabbit", - "text": "Cooked Rabbit: Restores 5 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:mackerel", - "text": "Mackerel: Restores 6 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:botanical_pie", - "text": "Botanical Pie: Restores 6 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:slimy_eel", - "text": "Slimy Eel: Restores 6-10 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:trout", - "text": "Trout: Restores 7 Hitpoints", - "level": "" - }, - { - "item": "rs:cod", - "text": "Cod: Restores 7 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:roast_rabbit", - "text": "Roast Rabbit: Restores 7 Hitpoints", - "level": "" - }, - { - "item": "rs:cave_eel", - "text": "Cave Eel: Restores 7-11 Hitpoints", - "level": "" - }, - { - "item": "rs:pike", - "text": "Pike: Restores 8 Hitpoints", - "level": "" - }, - { - "item": "rs:salmon", - "text": "Salmon: Restores 9 Hitpoints", - "level": "" - }, - { - "item": "rs:redberry_pie", - "text": "Redberry Pie: Restores 9 Hitpoints", - "level": "" - }, - { - "item": "rs:tuna", - "text": "Tuna: Restores 10 Hitpoints", - "level": "" - }, - { - "item": "rs:crab_meat", - "text": "Crab meat: Restores 10 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:fishcake", - "text": "Cooked Fishcake: Restores 11 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:jug_of_wine", - "text": "Jug of wine: Restores 11 Hitpoints", - "level": "" - }, - { - "item": "rs:meat_pie", - "text": "Meat pie: Restores 11 Hitpoints", - "level": "" - }, - { - "item": "rs:lava_eel", - "text": "Lava Eel: Restores 11 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:garden_pie", - "text": "Garden pie: Restores 12 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:fish_pie", - "text": "Fish pie: Restores 12 Hitpoints", - "level": "" - }, - { - "item": "rs:cake", - "text": "Cake: Restores 12 Hitpoints", - "level": "" - }, - { - "item": "rs:lobster", - "text": "Lobster: Restores 12 Hitpoints", - "level": "" - }, - { - "item": "rs:bass", - "text": "Bass: Restores 13 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:swordfish", - "text": "Swordfish: Restores 14 Hitpoints", - "level": "" - }, - { - "item": "rs:plain_pizza", - "text": "Plain pizza: Restores 14 Hitpoints", - "level": "" - }, - { - "item": "rs:apple_pie", - "text": "Apple pie: Restores 14 Hitpoints", - "level": "" - }, - { - "item": "rs:potato_with_butter", - "text": "Potato with butter: Restores 14 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:chilli_potato", - "text": "Chilli Potato: Restores 14 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:chocolate_cake", - "text": "Chocolate Cake: Restores 15 Hitpoints", - "level": "" - }, - { - "item": "rs:monkfish", - "text": "Monkfish: Restores 16 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:admiral_pie", - "text": "Admiral pie: Restores 16 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:meat_pizza", - "text": "Meat pizza: Restores 16 Hitpoints", - "level": "" - }, - { - "item": "rs:potato_with_cheese", - "text": "Potato with cheese: Restores 16 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:egg_potato", - "text": "Egg Potato: Restores 16 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:cooked_karambwan", - "text": "Cooked karambwan: Restores 18 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:anchovy_pizza", - "text": "Anchovy pizza: Restores 18 Hitpoints", - "level": "" - }, - { - "item": "rs:ugthanki_kebab", - "text": "Ugthanki kebab: Restores 19 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:jug_of_wine", - "text": "Jug of wine: Restores 11 Hitpoints", - "level": "" - }, - { - "item": "rs:shark", - "text": "Shark: Restores 20 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:mushroom_potato", - "text": "Mushroom Potato: Restores 20 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:sea_turtle", - "text": "Sea Turtle: Restores 21 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:manta_ray", - "text": "Manta Ray: Restores 22 Hitpoints", - "level": "" - }, - { - "item": "rs:tuna_potato", - "text": "Tuna Potato: Restores 22 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:wild_pie", - "text": "Wild pie: Restores 22 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:summer_pie", - "text": "Summer pie: Restores 22 Hitpoints\\n(Members only)", - "level": "" - }, - { - "item": "rs:pineapple_pizza", - "text": "Pineapple pizza: Restores 22 Hitpoints", - "level": "" - }, - { - "item": "rs:saradomin_brew", - "text": "Saradomin brew: Restores 15% of your\\nHitpoints level plus 2 - can boost beyond\\nyour level (members only)", - "level": "" - } - ] - } + }, + { + "name": "Healing", + "lines": [ + { + "item": "rs:purple_sweets", + "text": "Purple Sweets: Restores 1-3 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:anchovies", + "text": "Anchovies: Restores 1 Hitpoint", + "level": "" + }, + { + "item": "rs:shrimp", + "text": "Shrimp: Restores 3 Hitpoints", + "level": "" + }, + { + "item": "rs:cooked_chicken", + "text": "Cooked chicken: Restores 3 Hitpoints", + "level": "" + }, + { + "item": "rs:sardine", + "text": "Sardine: Restores 3 Hitpoints", + "level": "" + }, + { + "item": "rs:cooked_meat", + "text": "Cooked meat: Restores 3 Hitpoints", + "level": "" + }, + { + "item": "rs:bread", + "text": "Bread: Restores 5 Hitpoints", + "level": "" + }, + { + "item": "rs:bread", + "text": "Bread: Restores 5 Hitpoints", + "level": "" + }, + { + "item": "rs:herring", + "text": "Herring: Restores 5 Hitpoints", + "level": "" + }, + { + "item": "rs:cooked_rabbit", + "text": "Cooked Rabbit: Restores 5 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:mackerel", + "text": "Mackerel: Restores 6 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:botanical_pie", + "text": "Botanical Pie: Restores 6 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:slimy_eel", + "text": "Slimy Eel: Restores 6-10 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:trout", + "text": "Trout: Restores 7 Hitpoints", + "level": "" + }, + { + "item": "rs:cod", + "text": "Cod: Restores 7 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:roast_rabbit", + "text": "Roast Rabbit: Restores 7 Hitpoints", + "level": "" + }, + { + "item": "rs:cave_eel", + "text": "Cave Eel: Restores 7-11 Hitpoints", + "level": "" + }, + { + "item": "rs:pike", + "text": "Pike: Restores 8 Hitpoints", + "level": "" + }, + { + "item": "rs:salmon", + "text": "Salmon: Restores 9 Hitpoints", + "level": "" + }, + { + "item": "rs:redberry_pie", + "text": "Redberry Pie: Restores 9 Hitpoints", + "level": "" + }, + { + "item": "rs:tuna", + "text": "Tuna: Restores 10 Hitpoints", + "level": "" + }, + { + "item": "rs:crab_meat", + "text": "Crab meat: Restores 10 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:fishcake", + "text": "Cooked Fishcake: Restores 11 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:jug_of_wine", + "text": "Jug of wine: Restores 11 Hitpoints", + "level": "" + }, + { + "item": "rs:meat_pie", + "text": "Meat pie: Restores 11 Hitpoints", + "level": "" + }, + { + "item": "rs:lava_eel", + "text": "Lava Eel: Restores 11 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:garden_pie", + "text": "Garden pie: Restores 12 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:fish_pie", + "text": "Fish pie: Restores 12 Hitpoints", + "level": "" + }, + { + "item": "rs:cake", + "text": "Cake: Restores 12 Hitpoints", + "level": "" + }, + { + "item": "rs:lobster", + "text": "Lobster: Restores 12 Hitpoints", + "level": "" + }, + { + "item": "rs:bass", + "text": "Bass: Restores 13 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:swordfish", + "text": "Swordfish: Restores 14 Hitpoints", + "level": "" + }, + { + "item": "rs:plain_pizza", + "text": "Plain pizza: Restores 14 Hitpoints", + "level": "" + }, + { + "item": "rs:apple_pie", + "text": "Apple pie: Restores 14 Hitpoints", + "level": "" + }, + { + "item": "rs:potato_with_butter", + "text": "Potato with butter: Restores 14 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:chilli_potato", + "text": "Chilli Potato: Restores 14 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:chocolate_cake", + "text": "Chocolate Cake: Restores 15 Hitpoints", + "level": "" + }, + { + "item": "rs:monkfish", + "text": "Monkfish: Restores 16 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:admiral_pie", + "text": "Admiral pie: Restores 16 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:meat_pizza", + "text": "Meat pizza: Restores 16 Hitpoints", + "level": "" + }, + { + "item": "rs:potato_with_cheese", + "text": "Potato with cheese: Restores 16 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:egg_potato", + "text": "Egg Potato: Restores 16 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:cooked_karambwan", + "text": "Cooked karambwan: Restores 18 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:anchovy_pizza", + "text": "Anchovy pizza: Restores 18 Hitpoints", + "level": "" + }, + { + "item": "rs:ugthanki_kebab", + "text": "Ugthanki kebab: Restores 19 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:jug_of_wine", + "text": "Jug of wine: Restores 11 Hitpoints", + "level": "" + }, + { + "item": "rs:shark", + "text": "Shark: Restores 20 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:mushroom_potato", + "text": "Mushroom Potato: Restores 20 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:sea_turtle", + "text": "Sea Turtle: Restores 21 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:manta_ray", + "text": "Manta Ray: Restores 22 Hitpoints", + "level": "" + }, + { + "item": "rs:tuna_potato", + "text": "Tuna Potato: Restores 22 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:wild_pie", + "text": "Wild pie: Restores 22 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:summer_pie", + "text": "Summer pie: Restores 22 Hitpoints\\n(Members only)", + "level": "" + }, + { + "item": "rs:pineapple_pizza", + "text": "Pineapple pizza: Restores 22 Hitpoints", + "level": "" + }, + { + "item": "rs:saradomin_brew", + "text": "Saradomin brew: Restores 15% of your\\nHitpoints level plus 2 - can boost beyond\\nyour level (members only)", + "level": "" + } + ] + } ] - } - \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/magic.json b/src/plugins/skills/skill-guides/magic.json index efdbdb988..7dd8f61c8 100644 --- a/src/plugins/skills/skill-guides/magic.json +++ b/src/plugins/skills/skill-guides/magic.json @@ -3,812 +3,820 @@ "name": "Magic", "members": false, "sub_guides": [ - { - "name": "Normal Spells", - "lines": [ - { - "item": "rs:battle_staff", - "text": "Click a spell icon below to see the\\nrequired runes to cast each spell.\\n\\nBy opening the spellbook icon on the side\\n interface, you can see what each spell does\\nby moving your mouse over its icon.", - "level": "" - }, - { - "item": "rs:spell_home_teleport", - "text": "Click a spell icon below to see the\\nrequired runes to cast each spell.\\n\\nBy opening the spellbook icon on the side\\n interface, you can see what each spell does\\nby moving your mouse over its icon.", - "level": "" - }, - { - "item": "rs:spell_wind_strike", - "text": "Wind Strike", - "level": 1 - }, - { - "item": "rs:spell_confuse", - "text": "Confuse", - "level": 3 - }, - { - "item": "rs:spell_water_strike", - "text": "Water Strike", - "level": 5 - }, - { - "item": "rs:spell_level_1_enchant", - "text": "Level 1 enchant", - "level": 7 - }, - { - "item": "rs:spell_earth_strike", - "text": "Earth Strike", - "level": 9 - }, - { - "item": "rs:spell_weaken", - "text": "Weaken", - "level": 11 - }, - { - "item": "rs:spell_fire_strike", - "text": "Fire Strike", - "level": 13 - }, - { - "item": "rs:spell_bones_to_bananas", - "text": "Bones to bananas", - "level": 15 - }, - { - "item": "rs:spell_wind_bolt", - "text": "Wind Bolt", - "level": 17 - }, - { - "item": "rs:spell_curse", - "text": "Curse", - "level": 19 - }, - { - "item": "rs:spell_bind", - "text": "Bind", - "level": 20 - }, - { - "item": "rs:spell_low_level_alchemy", - "text": "Low level alchemy", - "level": 21 - }, - { - "item": "rs:spell_water_bolt", - "text": "Water Bolt", - "level": 23 - }, - { - "item": "rs:spell_varrock_teleport", - "text": "Varrock teleport", - "level": 25 - }, - { - "item": "rs:spell_level_2_enchant", - "text": "Level 2 enchant", - "level": 27 - }, - { - "item": "rs:spell_earth_bolt", - "text": "Earth Bolt", - "level": 29 - }, - { - "item": "rs:spell_lumbridge_teleport", - "text": "Lumbridge teleport", - "level": 31 - }, - { - "item": "rs:spell_telekinetic_grab", - "text": "Telekinetic grab", - "level": 33 - }, - { - "item": "rs:spell_fire_bolt", - "text": "Fire Bolt", - "level": 35 - }, - { - "item": "rs:spell_falador_teleport", - "text": "Falador teleport", - "level": 37 - }, - { - "item": "rs:spell_crumble_undead", - "text": "Crumble undead", - "level":39 - }, - { - "item": "rs:spell_teleport_to_house", - "text": "Teleport to house", - "level": 40 - }, - { - "item": "rs:spell_wind_blast", - "text": "Wind Blast", - "level": 41 - }, - { - "item": "rs:spell_superheat_item", - "text": "Superheat item", - "level": 43 - }, - { - "item": "rs:spell_camelot_teleport", - "text": "Members: Camelot teleport", - "level": 45 - }, - { - "item": "rs:spell_water_blast", - "text": "Water Blast", - "level": 47 - }, - { - "item": "rs:spell_level_3_enchant", - "text": "Level 3 enchant", - "level": 49 - }, - { - "item": "rs:spell_iban_blast", - "text": "Members: Iban blast\\n(after Underground Pass)", - "level": 50 - }, - { - "item": "rs:spell_snare", - "text": "Snare", - "level": 50 - }, - { - "item": "rs:spell_magic_dart", - "text": "Members: Magic dart\\n(with 55 Slayer)", - "level": 50 - }, - { - "item": "rs:spell_ardougne_teleport", - "text": "Members: Ardougne teleport\\n(after Plague City)", - "level": 51 - }, - { - "item": "rs:spell_earth_blast", - "text": "Earth Blast", - "level": 53 - }, - { - "item": "rs:spell_high_level_alchemy", - "text": "High level alchemy", - "level": 55 - }, - { - "item": "rs:spell_charge_water_orb", - "text": "Members: Charge water orb", - "level": 56 - }, - { - "item": "rs:spell_level_4_enchant", - "text": "Level 4 enchant", - "level": 57 - }, - { - "item": "rs:spell_watchtower_teleport", - "text": "Members: Watchtower teleport\\n(after Watchtower)", - "level": 58 - }, - { - "item": "rs:spell_fire_blast", - "text": "Fire Blast", - "level": 59 - }, - { - "item": "rs:spell_charge_earth_orb", - "text": "Members: Charge earth orb", - "level": 60 - }, - { - "item": "rs:spell_bones_to_peaches", - "text": "Members: Bones to peaches", - "level": 60 - }, - { - "item": "rs:spell_claws_of_guthix", - "text": "Members: Claws of Guthix\\n(after Mage Arena)", - "level": 60 - }, - { - "item": "rs:spell_flames_of_zamorak", - "text": "Members: Flames of Zamorak\\n(after Mage Arena", - "level": 60 - }, - { - "item": "rs:spell_saradomin_strike", - "text": "Members: Saradomin Strike\\n(after Mage Arena)", - "level": 60 - }, - { - "item": "rs:spell_trollheim_teleport", - "text": "Members: Trollheim teleport\\n(after Eadgar's Ruse)", - "level": 61 - }, - { - "item": "rs:spell_wind_wave", - "text": "Members: Wind Wave", - "level": 62 - }, - { - "item": "rs:spell_charge_fire_orb", - "text": "Members: Charge fire orb", - "level": 63 - }, - { - "item": "rs:spell_ape_atoll_teleport", - "text": "Members: Ape atoll teleport\\n(after Recipe for Disaster)", - "level": 64 - }, - { - "item": "rs:spell_water_wave", - "text": "Members: Water wave", - "level": 65 - }, - { - "item": "rs:spell_charge_air_orb", - "text": "Members: Charge air orb", - "level": 66 - }, - { - "item": "rs:spell_vulnerability", - "text": "Members: Vulnerability", - "level": 66 - }, - { - "item": "rs:spell_level_5_enchant", - "text": "Members: Level 5 enchant", - "level": 68 - }, - { - "item": "rs:spell_earth_wave", - "text": "Members: Earth Wave", - "level": 70 - }, - { - "item": "rs:spell_enfeeble", - "text": "Members: Enfeeble", - "level": 73 - }, - { - "item": "rs:spell_teleother_lumbridge", - "text": "Members: Teleother Lumbridge", - "level": 74 - }, - { - "item": "rs:spell_fire_wave", - "text": "Members: Fire Wave", - "level": 75 - }, - { - "item": "rs:spell_entangle", - "text": "Members: Entangle", - "level": 79 - }, - { - "item": "rs:spell_stun", - "text": "Members: Stun", - "level": 80 - }, - { - "item": "rs:spell_charge", - "text": "Members: Charge\\n(after Mage Arena)", - "level": 80 - }, - { - "item": "rs:spell_teleother_falador", - "text": "Members: Teleother to Falador", - "level": 82 - }, - { - "item": "rs:spell_tele_block", - "text": "Tele block", - "level": 85 - }, - { - "item": "rs:spell_level_6_enchant", - "text": "Level 6 enchant", - "level": 87 - }, - { - "item": "rs:spell_teleother_camelot", - "text": "Members: Teleother to Camelot", - "level": 90 - } - ] - },{ - "name": "Ancient Magicks", - "members": true, - "lines": [ - { - "item": "rs:ancient_magick_guide", - "text": "Ancient magicks are available after\\ncompleting the Desert Treasure quest.", - "level": "" - }, - { - "item": "rs:spell_home_teleport_ancient", - "text": "Home teleport (Edgeville)", - "level": "" - }, - { - "item": "rs:spell_smoke_rush", - "text": "Smoke rush", - "level": 50 - }, - { - "item": "rs:spell_shadow_rush", - "text": "Shadow rush", - "level": 52 - }, - { - "item": "rs:spell_paddewwa_teleport", - "text": "Paddewwa teleport", - "level": 54 - }, - { - "item": "rs:spell_blood_rush", - "text": "Blood rush", - "level": 56 - }, - { - "item": "rs:spell_ice_rush", - "text": "Mithril", - "level": 58 - }, - { - "item": "rs:spell_senntisten_teleport", - "text": "Senntisten teleport", - "level": 60 - }, - { - "item": "rs:spell_smoke_burst", - "text": "Smoke burst", - "level": 62 - }, - { - "item": "rs:spell_shadow_burst", - "text": "Shadow burst", - "level": 64 - }, - { - "item": "rs:Kharyll teleport", - "text": "Kharyll teleport", - "level": 66 - }, - { - "item": "rs:spell_blood_burst", - "text": "Blood burst", - "level": 68 - }, - { - "item": "rs:spell_ice_burst", - "text": "Ice burst", - "level": 70 - }, - { - "item": "rs:spell_lassar_teleport", - "text": "Lassar teleport", - "level": 72 - }, - { - "item": "rs:spell_smoke_blitz", - "text": "Smoke Blitz", - "level": 74 - }, - { - "item": "rs:spell_shadow_blitz", - "text": "Shadow blitz", - "level": 76 - }, - { - "item": "rs:spell_dareeyak_teleport", - "text": "Dareeyak teleport", - "level": 78 - }, - { - "item": "rs:spell_blood_blitz", - "text": "Blood Blitz", - "level": 80 - }, - { - "item": "rs:spell_ice_blitz", - "text": "Ice blitz", - "level": 82 - }, - { - "item": "rs:guthans_warspear", - "text": "Members: Guthan's warspear", - "level": 84 - }, - { - "item": "rs:spell_carrallangar_teleport", - "text": "Carrallangar teleport", - "level": 85 - }, - { - "item": "rs:spell_smoke_barrage", - "text": "Smoke barrage", - "level": 86 - }, - { - "item": "rs:spell_shadow_barrage", - "text": "Shadow barrage", - "level": 88 - }, - { - "item": "rs:spell_annakarl teleport", - "text": "Annakarl teleport", - "level": 90 - }, - { - "item": "rs:spell_blood_barrage", - "text": "Blood barrage", - "level": 92 - }, - { - "item": "rs:spell_ice_barrage", - "text": "Ice barrage", - "level": 94 - }, - { - "item": "rs:spell_ghorrock_teleport", - "text": "Ghorrock teleport", - "level": 96 - } - ] - },{ - "name": "Lunar Spells", - "members": true, - "lines": [ - { - "item": "rs:lunar_spells_guide", - "text": "Lunar spells are available after completing\\nthe Lunar Diplomacy quest.", - "level": "" - }, - { - "item": "rs:spell_home_teleport_lunar", - "text": "Home teleport (Lunar Isle)", - "level": "" - }, - { - "item": "rs:spell_bake_pie", - "text": "Bake pie", - "level": 65 - }, - { - "item": "rs:spell_geomancy", - "text": "Geomancy", - "level": 65 - }, - { - "item": "rs:spell_cure_plant", - "text": "Cure plant", - "level": 66 - }, - { - "item": "rs:spell_npc_contact", - "text": "NPC Contact", - "level": 67 - }, - { - "item": "rs:spell_cure_other", - "text": "Cure other", - "level": 68 - }, - { - "item": "rs:spell_moonclan_teleport", - "text": "Moonclan teleport", - "level": 69 - }, - { - "item": "rs:spell_telegroup_moonclan", - "text": "Tele group Moonclan", - "level": 70 - }, - { - "item": "rs:spell_cure_me", - "text": "Cure me", - "level": 71 - }, - { - "item": "rs:spell_ourania_teleport", - "text": "Ourania teleport", - "level": 71 - }, - { - "item": "rs:spell_waterbirth_teleport", - "text": "Waterbirth teleport", - "level": 72 - }, - { - "item": "rs:spell_telegroup_waterbirth", - "text": "Tele group Waterbirth", - "level": 73 - }, - { - "item": "rs:spell_barbarian_teleport", - "text": "Barbarian teleport", - "level": 72 - }, - { - "item": "rs:spell_telegroup_barbarian", - "text": "Tele group Barbarian", - "level": 74 - }, - { - "item": "rs:spell_spin_flax", - "text": "Spin Flax", - "level": 76 - }, - { - "item": "rs:spell_superglass_make", - "text": "Superglass make", - "level": 77 - }, - { - "item": "rs:spell_khazard_teleport", - "text": "Khazard teleport", - "level": 78 - }, - { - "item": "rs:spell_telegroup_khazard", - "text": "Tele group Khazard", - "level": 79 - }, - { - "item": "rs:spell_string_jewellery", - "text": "String jewellery", - "level": 80 - }, - { - "item": "rs:spell_stat_restore_pot_share", - "text": "Stat restore pot share", - "level": 81 - }, - { - "item": "rs:spell_magic_imbue", - "text": "Magic imbue", - "level": 82 - }, - { - "item": "rs:spell_fertile_soil", - "text": "Fertile soil", - "level": 83 - }, - { - "item": "rs:spell_boost_potion_share", - "text": "Boost potion share", - "level": 84 - }, - { - "item": "rs:spell_fishing_guild_teleport", - "text": "Fishing guild teleport", - "level": 85 - }, - { - "item": "rs:spell_telegroup_fishing_guild", - "text": "Tele group fishing guild", - "level": 86 - }, - { - "item": "rs:spell_catherby_teleport", - "text": "Catherby teleport", - "level": 87 - }, - { - "item": "rs:spell_telegroup_catherby", - "text": "Tele group Catherby", - "level": 88 - }, - { - "item": "rs:spell_recharge_dragonstone", - "text": "Recharge Dragonstone", - "level": 89 - }, - { - "item": "rs:spell_ice_plateau_teleport", - "text": "Ice plateau teleport", - "level": 89 - }, - { - "item": "rs:spell_telegroup_ice_plateau", - "text": "Tele group Ice plateau", - "level": 90 - }, - { - "item": "rs:spell_energy_transfer", - "text": "Energy transfer", - "level": 91 - }, - { - "item": "rs:spell_heal_other", - "text": "Heal other", - "level": 92 - }, - { - "item": "rs:spell_vengeance_other", - "text": "Vengeance other", - "level": 93 - }, - { - "item": "rs:spell_vengeancer", - "text": "Vengeance", - "level": 94 - }, - { - "item": "rs:spell_heal_group", - "text": "Heal group", - "level": 95 - } - ] - },{ - "name": "Armour", - "members": true, - "lines": [ - { - "item": "rs:wizard_boots", - "text": "Wizard boots", - "level": 20 - }, - { - "item": "rsmystic_robes", - "text": "Mystic robes\\n(20 Defence required)", - "level": 40 - }, - { - "item": "rs:enchanted_robes", - "text": "Enchanted robes\\n(20 Defence required)", - "level": 40 - }, - { - "item": "rs:splitbark_armour", - "text": "Splitbark armour\\n(40 Defence required)", - "level": 40 - }, - { - "item": "rs:skeletal_armour", - "text": "Skeletal_armour\\n(after The Fremmenik Trials, 40 Defence required", - "level": 40 - }, - { - "item": "rs:infinity_robes", - "text": "Infinity robes\\n(25 Defence required)", - "level": 50 - }, - { - "item": "rs:god_capes", - "text": "God capes\\n(after Mage Arena)", - "level": 60 - }, - { - "item": "rs:lunar_armour", - "text": "Lunar armour\\n(after Lunar Diplomacy, 40 Defence required)", - "level": 65 - }, - { - "item": "rs:ahrims_robes", - "text": "Ahrims robes\\n(with 70 Defence)", - "level": 70 - } - ] - },{ - "name": "Bolts", - "members": true, - "lines": [ - { - "item": "rs:spell_enchant_opal_tipped_crossbow_bolts", - "text": "Opal-tipped crossbow bolts\\n1 cosmic + 2 air runes", - "level": 4 - }, { - "item": "rs:spell_enchant_sapphire_tipped_crossbow_bolts", - "text": "Sapphire-tipped crossbow bolts\\n1 cosmic + 1 water + 1 mind rune", - "level": 7 - }, - { - "item": "rs:spell_enchant_jade_tipped_crossbow_bolts", - "text": "Jade-tipped crossbow bolts\\n1 cosmic + 2 earth runes", - "level": 14 - }, - { - "item": "rs:spell_enchant_pearl_tipped_crossbow_bolts", - "text": "Pearl-tipped crossbow bolts\\n1 cosmic + 2 water runes", - "level": 24 - }, - { - "item": "rs:spell_enchant_emerald_tipped_crossbow_bolts", - "text": "Emerald-tipped crossbow bolts\\n1 cosmic + 3 air runes + 1 nature rune", - "level": 27 - }, - { - "item": "rs:spell_enchant_red_topaz_tipped_crossbow_bolts", - "text": "Red topaz-tipped crossbow bolts\\n1 cosmic + 2 blood runes", - "level": 29 - }, - { - "item": "rs:spell_enchant_ruby_tipped_crossbow_bolts", - "text": "Opal-tipped crossbow bolts\\n1 cosmic + 5 fire + 1 blood runes", - "level": 49 - }, - { - "item": "rs:spell_enchant_diamond_tipped_crossbow_bolts", - "text": "Diamond-tipped crossbow bolts\\n1 cosmic + 10 earth + 2 law runes", - "level": 57 - }, - { - "item": "rs:spell_enchant_dragonstone_tipped_crossbow_bolts", - "text": "Dragonstone-tipped crossbow bolts\\n1 cosmic + 15 earth + 1 soul runes", - "level": 68 - }, - { - "item": "rs:spell_enchant_onyx_tipped_crossbow_bolts", - "text": "Onyx-tipped crossbow bolts\\n1 cosmic + 20 fire + 1 death runes", - "level": 87 - } - ] - },{ - "name": "Weapons", - "members": true, - "lines": [ - { - "item": "rs:battlestaves", - "text": "Battlestaves\\n(30 Attack required)", - "level": 20 - }, - { - "item": "rs:mysticstaves", - "text": "Mystic staves\\n(40 Attack required)", - "level": 40 - }, - { - "item": "rs:beginner_wand", - "text": "Beginner wand", - "level": 45 - }, - { - "item": "rs:apprentice_wand", - "text": "Apprentice wand", - "level": 50 - }, - { - "item": "rs:ancient_staff", - "text": "Ancient staff\\n(after Desert Treasure, 50 Attack required", - "level": 50 - }, - { - "item": "rs:slayer_staff", - "text": "Slayer staff\\n(with 55 Slayer)", - "level": 50 - }, - { - "item": "rs:teacher_wand", - "text": "Teacher wand", - "level": 55 - }, - { - "item": "rs:master_wand", - "text": "Master wand", - "level": 60 - }, { - "item": "rs:god_staves", - "text": "God staves\\n(after Mage Arena)", - "level": 60 - }, { - "item": "rs:toktz-mej-tal", - "text": "TokTz-Mej-Tal\\n(60 Attack required)", - "level": 60 - }, - { - "item": "rs:ahrims_robes", - "text": "Ahrim's staff\\n(70 Attack required)", - "level": 70 - } - ] - } + { + "name": "Normal Spells", + "lines": [ + { + "item": "rs:battle_staff", + "text": "Click a spell icon below to see the\\nrequired runes to cast each spell.\\n\\nBy opening the spellbook icon on the side\\n interface, you can see what each spell does\\nby moving your mouse over its icon.", + "level": "" + }, + { + "item": "rs:spell_home_teleport", + "text": "Click a spell icon below to see the\\nrequired runes to cast each spell.\\n\\nBy opening the spellbook icon on the side\\n interface, you can see what each spell does\\nby moving your mouse over its icon.", + "level": "" + }, + { + "item": "rs:spell_wind_strike", + "text": "Wind Strike", + "level": 1 + }, + { + "item": "rs:spell_confuse", + "text": "Confuse", + "level": 3 + }, + { + "item": "rs:spell_water_strike", + "text": "Water Strike", + "level": 5 + }, + { + "item": "rs:spell_level_1_enchant", + "text": "Level 1 enchant", + "level": 7 + }, + { + "item": "rs:spell_earth_strike", + "text": "Earth Strike", + "level": 9 + }, + { + "item": "rs:spell_weaken", + "text": "Weaken", + "level": 11 + }, + { + "item": "rs:spell_fire_strike", + "text": "Fire Strike", + "level": 13 + }, + { + "item": "rs:spell_bones_to_bananas", + "text": "Bones to bananas", + "level": 15 + }, + { + "item": "rs:spell_wind_bolt", + "text": "Wind Bolt", + "level": 17 + }, + { + "item": "rs:spell_curse", + "text": "Curse", + "level": 19 + }, + { + "item": "rs:spell_bind", + "text": "Bind", + "level": 20 + }, + { + "item": "rs:spell_low_level_alchemy", + "text": "Low level alchemy", + "level": 21 + }, + { + "item": "rs:spell_water_bolt", + "text": "Water Bolt", + "level": 23 + }, + { + "item": "rs:spell_varrock_teleport", + "text": "Varrock teleport", + "level": 25 + }, + { + "item": "rs:spell_level_2_enchant", + "text": "Level 2 enchant", + "level": 27 + }, + { + "item": "rs:spell_earth_bolt", + "text": "Earth Bolt", + "level": 29 + }, + { + "item": "rs:spell_lumbridge_teleport", + "text": "Lumbridge teleport", + "level": 31 + }, + { + "item": "rs:spell_telekinetic_grab", + "text": "Telekinetic grab", + "level": 33 + }, + { + "item": "rs:spell_fire_bolt", + "text": "Fire Bolt", + "level": 35 + }, + { + "item": "rs:spell_falador_teleport", + "text": "Falador teleport", + "level": 37 + }, + { + "item": "rs:spell_crumble_undead", + "text": "Crumble undead", + "level": 39 + }, + { + "item": "rs:spell_teleport_to_house", + "text": "Teleport to house", + "level": 40 + }, + { + "item": "rs:spell_wind_blast", + "text": "Wind Blast", + "level": 41 + }, + { + "item": "rs:spell_superheat_item", + "text": "Superheat item", + "level": 43 + }, + { + "item": "rs:spell_camelot_teleport", + "text": "Members: Camelot teleport", + "level": 45 + }, + { + "item": "rs:spell_water_blast", + "text": "Water Blast", + "level": 47 + }, + { + "item": "rs:spell_level_3_enchant", + "text": "Level 3 enchant", + "level": 49 + }, + { + "item": "rs:spell_iban_blast", + "text": "Members: Iban blast\\n(after Underground Pass)", + "level": 50 + }, + { + "item": "rs:spell_snare", + "text": "Snare", + "level": 50 + }, + { + "item": "rs:spell_magic_dart", + "text": "Members: Magic dart\\n(with 55 Slayer)", + "level": 50 + }, + { + "item": "rs:spell_ardougne_teleport", + "text": "Members: Ardougne teleport\\n(after Plague City)", + "level": 51 + }, + { + "item": "rs:spell_earth_blast", + "text": "Earth Blast", + "level": 53 + }, + { + "item": "rs:spell_high_level_alchemy", + "text": "High level alchemy", + "level": 55 + }, + { + "item": "rs:spell_charge_water_orb", + "text": "Members: Charge water orb", + "level": 56 + }, + { + "item": "rs:spell_level_4_enchant", + "text": "Level 4 enchant", + "level": 57 + }, + { + "item": "rs:spell_watchtower_teleport", + "text": "Members: Watchtower teleport\\n(after Watchtower)", + "level": 58 + }, + { + "item": "rs:spell_fire_blast", + "text": "Fire Blast", + "level": 59 + }, + { + "item": "rs:spell_charge_earth_orb", + "text": "Members: Charge earth orb", + "level": 60 + }, + { + "item": "rs:spell_bones_to_peaches", + "text": "Members: Bones to peaches", + "level": 60 + }, + { + "item": "rs:spell_claws_of_guthix", + "text": "Members: Claws of Guthix\\n(after Mage Arena)", + "level": 60 + }, + { + "item": "rs:spell_flames_of_zamorak", + "text": "Members: Flames of Zamorak\\n(after Mage Arena", + "level": 60 + }, + { + "item": "rs:spell_saradomin_strike", + "text": "Members: Saradomin Strike\\n(after Mage Arena)", + "level": 60 + }, + { + "item": "rs:spell_trollheim_teleport", + "text": "Members: Trollheim teleport\\n(after Eadgar's Ruse)", + "level": 61 + }, + { + "item": "rs:spell_wind_wave", + "text": "Members: Wind Wave", + "level": 62 + }, + { + "item": "rs:spell_charge_fire_orb", + "text": "Members: Charge fire orb", + "level": 63 + }, + { + "item": "rs:spell_ape_atoll_teleport", + "text": "Members: Ape atoll teleport\\n(after Recipe for Disaster)", + "level": 64 + }, + { + "item": "rs:spell_water_wave", + "text": "Members: Water wave", + "level": 65 + }, + { + "item": "rs:spell_charge_air_orb", + "text": "Members: Charge air orb", + "level": 66 + }, + { + "item": "rs:spell_vulnerability", + "text": "Members: Vulnerability", + "level": 66 + }, + { + "item": "rs:spell_level_5_enchant", + "text": "Members: Level 5 enchant", + "level": 68 + }, + { + "item": "rs:spell_earth_wave", + "text": "Members: Earth Wave", + "level": 70 + }, + { + "item": "rs:spell_enfeeble", + "text": "Members: Enfeeble", + "level": 73 + }, + { + "item": "rs:spell_teleother_lumbridge", + "text": "Members: Teleother Lumbridge", + "level": 74 + }, + { + "item": "rs:spell_fire_wave", + "text": "Members: Fire Wave", + "level": 75 + }, + { + "item": "rs:spell_entangle", + "text": "Members: Entangle", + "level": 79 + }, + { + "item": "rs:spell_stun", + "text": "Members: Stun", + "level": 80 + }, + { + "item": "rs:spell_charge", + "text": "Members: Charge\\n(after Mage Arena)", + "level": 80 + }, + { + "item": "rs:spell_teleother_falador", + "text": "Members: Teleother to Falador", + "level": 82 + }, + { + "item": "rs:spell_tele_block", + "text": "Tele block", + "level": 85 + }, + { + "item": "rs:spell_level_6_enchant", + "text": "Level 6 enchant", + "level": 87 + }, + { + "item": "rs:spell_teleother_camelot", + "text": "Members: Teleother to Camelot", + "level": 90 + } + ] + }, + { + "name": "Ancient Magicks", + "members": true, + "lines": [ + { + "item": "rs:ancient_magick_guide", + "text": "Ancient magicks are available after\\ncompleting the Desert Treasure quest.", + "level": "" + }, + { + "item": "rs:spell_home_teleport_ancient", + "text": "Home teleport (Edgeville)", + "level": "" + }, + { + "item": "rs:spell_smoke_rush", + "text": "Smoke rush", + "level": 50 + }, + { + "item": "rs:spell_shadow_rush", + "text": "Shadow rush", + "level": 52 + }, + { + "item": "rs:spell_paddewwa_teleport", + "text": "Paddewwa teleport", + "level": 54 + }, + { + "item": "rs:spell_blood_rush", + "text": "Blood rush", + "level": 56 + }, + { + "item": "rs:spell_ice_rush", + "text": "Mithril", + "level": 58 + }, + { + "item": "rs:spell_senntisten_teleport", + "text": "Senntisten teleport", + "level": 60 + }, + { + "item": "rs:spell_smoke_burst", + "text": "Smoke burst", + "level": 62 + }, + { + "item": "rs:spell_shadow_burst", + "text": "Shadow burst", + "level": 64 + }, + { + "item": "rs:Kharyll teleport", + "text": "Kharyll teleport", + "level": 66 + }, + { + "item": "rs:spell_blood_burst", + "text": "Blood burst", + "level": 68 + }, + { + "item": "rs:spell_ice_burst", + "text": "Ice burst", + "level": 70 + }, + { + "item": "rs:spell_lassar_teleport", + "text": "Lassar teleport", + "level": 72 + }, + { + "item": "rs:spell_smoke_blitz", + "text": "Smoke Blitz", + "level": 74 + }, + { + "item": "rs:spell_shadow_blitz", + "text": "Shadow blitz", + "level": 76 + }, + { + "item": "rs:spell_dareeyak_teleport", + "text": "Dareeyak teleport", + "level": 78 + }, + { + "item": "rs:spell_blood_blitz", + "text": "Blood Blitz", + "level": 80 + }, + { + "item": "rs:spell_ice_blitz", + "text": "Ice blitz", + "level": 82 + }, + { + "item": "rs:guthans_warspear", + "text": "Members: Guthan's warspear", + "level": 84 + }, + { + "item": "rs:spell_carrallangar_teleport", + "text": "Carrallangar teleport", + "level": 85 + }, + { + "item": "rs:spell_smoke_barrage", + "text": "Smoke barrage", + "level": 86 + }, + { + "item": "rs:spell_shadow_barrage", + "text": "Shadow barrage", + "level": 88 + }, + { + "item": "rs:spell_annakarl teleport", + "text": "Annakarl teleport", + "level": 90 + }, + { + "item": "rs:spell_blood_barrage", + "text": "Blood barrage", + "level": 92 + }, + { + "item": "rs:spell_ice_barrage", + "text": "Ice barrage", + "level": 94 + }, + { + "item": "rs:spell_ghorrock_teleport", + "text": "Ghorrock teleport", + "level": 96 + } + ] + }, + { + "name": "Lunar Spells", + "members": true, + "lines": [ + { + "item": "rs:lunar_spells_guide", + "text": "Lunar spells are available after completing\\nthe Lunar Diplomacy quest.", + "level": "" + }, + { + "item": "rs:spell_home_teleport_lunar", + "text": "Home teleport (Lunar Isle)", + "level": "" + }, + { + "item": "rs:spell_bake_pie", + "text": "Bake pie", + "level": 65 + }, + { + "item": "rs:spell_geomancy", + "text": "Geomancy", + "level": 65 + }, + { + "item": "rs:spell_cure_plant", + "text": "Cure plant", + "level": 66 + }, + { + "item": "rs:spell_npc_contact", + "text": "NPC Contact", + "level": 67 + }, + { + "item": "rs:spell_cure_other", + "text": "Cure other", + "level": 68 + }, + { + "item": "rs:spell_moonclan_teleport", + "text": "Moonclan teleport", + "level": 69 + }, + { + "item": "rs:spell_telegroup_moonclan", + "text": "Tele group Moonclan", + "level": 70 + }, + { + "item": "rs:spell_cure_me", + "text": "Cure me", + "level": 71 + }, + { + "item": "rs:spell_ourania_teleport", + "text": "Ourania teleport", + "level": 71 + }, + { + "item": "rs:spell_waterbirth_teleport", + "text": "Waterbirth teleport", + "level": 72 + }, + { + "item": "rs:spell_telegroup_waterbirth", + "text": "Tele group Waterbirth", + "level": 73 + }, + { + "item": "rs:spell_barbarian_teleport", + "text": "Barbarian teleport", + "level": 72 + }, + { + "item": "rs:spell_telegroup_barbarian", + "text": "Tele group Barbarian", + "level": 74 + }, + { + "item": "rs:spell_spin_flax", + "text": "Spin Flax", + "level": 76 + }, + { + "item": "rs:spell_superglass_make", + "text": "Superglass make", + "level": 77 + }, + { + "item": "rs:spell_khazard_teleport", + "text": "Khazard teleport", + "level": 78 + }, + { + "item": "rs:spell_telegroup_khazard", + "text": "Tele group Khazard", + "level": 79 + }, + { + "item": "rs:spell_string_jewellery", + "text": "String jewellery", + "level": 80 + }, + { + "item": "rs:spell_stat_restore_pot_share", + "text": "Stat restore pot share", + "level": 81 + }, + { + "item": "rs:spell_magic_imbue", + "text": "Magic imbue", + "level": 82 + }, + { + "item": "rs:spell_fertile_soil", + "text": "Fertile soil", + "level": 83 + }, + { + "item": "rs:spell_boost_potion_share", + "text": "Boost potion share", + "level": 84 + }, + { + "item": "rs:spell_fishing_guild_teleport", + "text": "Fishing guild teleport", + "level": 85 + }, + { + "item": "rs:spell_telegroup_fishing_guild", + "text": "Tele group fishing guild", + "level": 86 + }, + { + "item": "rs:spell_catherby_teleport", + "text": "Catherby teleport", + "level": 87 + }, + { + "item": "rs:spell_telegroup_catherby", + "text": "Tele group Catherby", + "level": 88 + }, + { + "item": "rs:spell_recharge_dragonstone", + "text": "Recharge Dragonstone", + "level": 89 + }, + { + "item": "rs:spell_ice_plateau_teleport", + "text": "Ice plateau teleport", + "level": 89 + }, + { + "item": "rs:spell_telegroup_ice_plateau", + "text": "Tele group Ice plateau", + "level": 90 + }, + { + "item": "rs:spell_energy_transfer", + "text": "Energy transfer", + "level": 91 + }, + { + "item": "rs:spell_heal_other", + "text": "Heal other", + "level": 92 + }, + { + "item": "rs:spell_vengeance_other", + "text": "Vengeance other", + "level": 93 + }, + { + "item": "rs:spell_vengeancer", + "text": "Vengeance", + "level": 94 + }, + { + "item": "rs:spell_heal_group", + "text": "Heal group", + "level": 95 + } + ] + }, + { + "name": "Armour", + "members": true, + "lines": [ + { + "item": "rs:wizard_boots", + "text": "Wizard boots", + "level": 20 + }, + { + "item": "rsmystic_robes", + "text": "Mystic robes\\n(20 Defence required)", + "level": 40 + }, + { + "item": "rs:enchanted_robes", + "text": "Enchanted robes\\n(20 Defence required)", + "level": 40 + }, + { + "item": "rs:splitbark_armour", + "text": "Splitbark armour\\n(40 Defence required)", + "level": 40 + }, + { + "item": "rs:skeletal_armour", + "text": "Skeletal_armour\\n(after The Fremmenik Trials, 40 Defence required", + "level": 40 + }, + { + "item": "rs:infinity_robes", + "text": "Infinity robes\\n(25 Defence required)", + "level": 50 + }, + { + "item": "rs:god_capes", + "text": "God capes\\n(after Mage Arena)", + "level": 60 + }, + { + "item": "rs:lunar_armour", + "text": "Lunar armour\\n(after Lunar Diplomacy, 40 Defence required)", + "level": 65 + }, + { + "item": "rs:ahrims_robes", + "text": "Ahrims robes\\n(with 70 Defence)", + "level": 70 + } + ] + }, + { + "name": "Bolts", + "members": true, + "lines": [ + { + "item": "rs:spell_enchant_opal_tipped_crossbow_bolts", + "text": "Opal-tipped crossbow bolts\\n1 cosmic + 2 air runes", + "level": 4 + }, + { + "item": "rs:spell_enchant_sapphire_tipped_crossbow_bolts", + "text": "Sapphire-tipped crossbow bolts\\n1 cosmic + 1 water + 1 mind rune", + "level": 7 + }, + { + "item": "rs:spell_enchant_jade_tipped_crossbow_bolts", + "text": "Jade-tipped crossbow bolts\\n1 cosmic + 2 earth runes", + "level": 14 + }, + { + "item": "rs:spell_enchant_pearl_tipped_crossbow_bolts", + "text": "Pearl-tipped crossbow bolts\\n1 cosmic + 2 water runes", + "level": 24 + }, + { + "item": "rs:spell_enchant_emerald_tipped_crossbow_bolts", + "text": "Emerald-tipped crossbow bolts\\n1 cosmic + 3 air runes + 1 nature rune", + "level": 27 + }, + { + "item": "rs:spell_enchant_red_topaz_tipped_crossbow_bolts", + "text": "Red topaz-tipped crossbow bolts\\n1 cosmic + 2 blood runes", + "level": 29 + }, + { + "item": "rs:spell_enchant_ruby_tipped_crossbow_bolts", + "text": "Opal-tipped crossbow bolts\\n1 cosmic + 5 fire + 1 blood runes", + "level": 49 + }, + { + "item": "rs:spell_enchant_diamond_tipped_crossbow_bolts", + "text": "Diamond-tipped crossbow bolts\\n1 cosmic + 10 earth + 2 law runes", + "level": 57 + }, + { + "item": "rs:spell_enchant_dragonstone_tipped_crossbow_bolts", + "text": "Dragonstone-tipped crossbow bolts\\n1 cosmic + 15 earth + 1 soul runes", + "level": 68 + }, + { + "item": "rs:spell_enchant_onyx_tipped_crossbow_bolts", + "text": "Onyx-tipped crossbow bolts\\n1 cosmic + 20 fire + 1 death runes", + "level": 87 + } + ] + }, + { + "name": "Weapons", + "members": true, + "lines": [ + { + "item": "rs:battlestaves", + "text": "Battlestaves\\n(30 Attack required)", + "level": 20 + }, + { + "item": "rs:mysticstaves", + "text": "Mystic staves\\n(40 Attack required)", + "level": 40 + }, + { + "item": "rs:beginner_wand", + "text": "Beginner wand", + "level": 45 + }, + { + "item": "rs:apprentice_wand", + "text": "Apprentice wand", + "level": 50 + }, + { + "item": "rs:ancient_staff", + "text": "Ancient staff\\n(after Desert Treasure, 50 Attack required", + "level": 50 + }, + { + "item": "rs:slayer_staff", + "text": "Slayer staff\\n(with 55 Slayer)", + "level": 50 + }, + { + "item": "rs:teacher_wand", + "text": "Teacher wand", + "level": 55 + }, + { + "item": "rs:master_wand", + "text": "Master wand", + "level": 60 + }, + { + "item": "rs:god_staves", + "text": "God staves\\n(after Mage Arena)", + "level": 60 + }, + { + "item": "rs:toktz-mej-tal", + "text": "TokTz-Mej-Tal\\n(60 Attack required)", + "level": 60 + }, + { + "item": "rs:ahrims_robes", + "text": "Ahrim's staff\\n(70 Attack required)", + "level": 70 + } + ] + } ] - } +} diff --git a/src/plugins/skills/skill-guides/mining.json b/src/plugins/skills/skill-guides/mining.json index c03d048e5..ad664ff8d 100644 --- a/src/plugins/skills/skill-guides/mining.json +++ b/src/plugins/skills/skill-guides/mining.json @@ -1,132 +1,132 @@ { - "id": 120, - "name": "Mining", - "members": false, - "sub_guides": [ - { - "name": "Rocks", - "lines": [ - { - "item": "rs:rune_essence", - "text": "Rune essence (after RuneMysteries quest)", - "level": 1 - }, - { - "item": "rs:clay", - "text": "Clay", - "level": 1 - }, - { - "item": "rs:copper_ore", - "text": "Copper ore", - "level": 1 - }, - { - "item": "rs:tin_ore", - "text": "Tin ore", - "level": 1 - }, - { - "item": "rs:blurite_ore", - "text": "Blurite ore", - "level": 10 - }, - { - "item": "rs:limestone", - "text": "Members: Limestone", - "level": 10 - }, - { - "item": "rs:iron_ore", - "text": "Iron ore", - "level": 15 - }, - { - "item": "rs:silver_ore", - "text": "Silver ore", - "level": 20 - }, - { - "item": "rs:coal", - "text": "Coal", - "level": 30 - }, - { - "item": "rs:gold_ore", - "text": "Gold", - "level": 40 - }, - { - "item": "rs:granite", - "text": "Members: Granite", - "level": 45 - }, - { - "item": "rs:mithril_ore", - "text": "Mithril ore", - "level": 55 - }, - { - "item": "rs:adamantite_ore", - "text": "Adamantite ore", - "level": 70 - }, - { - "item": "rs:soft_clay", - "text": "Members: Soft clay", - "level": 70 - }, - { - "item": "rs:runite_ore", - "text": "Runite ore", - "level": 85 - } - ] - }, - { - "name": "Equipment", - "lines": [ - { - "item": "rs:bronze_pickaxe", - "text": "Bronze pickaxe", - "level": 1 - }, - { - "item": "rs:iron_pickaxe", - "text": "Iron pickaxe", - "level": 1 - }, - { - "item": "rs:steel_pickaxe", - "text": "Steel pickaxe", - "level": 6 - }, - { - "item": "rs:mithril_pickaxe", - "text": "Mithril pickaxe", - "level": 21 - }, - { - "item": "rs:adamant_pickaxe", - "text": "Adamant pickaxe", - "level": 31 - }, - { - "item": "rs:rune_pickaxe", - "text": "Rune pickaxe", - "level": 41 - } - ] - }, - { - "name": "Areas", - "lines": [ - { - "item": "rs:mithril_ore", - "text": "Mining guild", - "level": 60 + "id": 120, + "name": "Mining", + "members": false, + "sub_guides": [ + { + "name": "Rocks", + "lines": [ + { + "item": "rs:rune_essence", + "text": "Rune essence (after RuneMysteries quest)", + "level": 1 + }, + { + "item": "rs:clay", + "text": "Clay", + "level": 1 + }, + { + "item": "rs:copper_ore", + "text": "Copper ore", + "level": 1 + }, + { + "item": "rs:tin_ore", + "text": "Tin ore", + "level": 1 + }, + { + "item": "rs:blurite_ore", + "text": "Blurite ore", + "level": 10 + }, + { + "item": "rs:limestone", + "text": "Members: Limestone", + "level": 10 + }, + { + "item": "rs:iron_ore", + "text": "Iron ore", + "level": 15 + }, + { + "item": "rs:silver_ore", + "text": "Silver ore", + "level": 20 + }, + { + "item": "rs:coal", + "text": "Coal", + "level": 30 + }, + { + "item": "rs:gold_ore", + "text": "Gold", + "level": 40 + }, + { + "item": "rs:granite", + "text": "Members: Granite", + "level": 45 + }, + { + "item": "rs:mithril_ore", + "text": "Mithril ore", + "level": 55 + }, + { + "item": "rs:adamantite_ore", + "text": "Adamantite ore", + "level": 70 + }, + { + "item": "rs:soft_clay", + "text": "Members: Soft clay", + "level": 70 + }, + { + "item": "rs:runite_ore", + "text": "Runite ore", + "level": 85 + } + ] + }, + { + "name": "Equipment", + "lines": [ + { + "item": "rs:bronze_pickaxe", + "text": "Bronze pickaxe", + "level": 1 + }, + { + "item": "rs:iron_pickaxe", + "text": "Iron pickaxe", + "level": 1 + }, + { + "item": "rs:steel_pickaxe", + "text": "Steel pickaxe", + "level": 6 + }, + { + "item": "rs:mithril_pickaxe", + "text": "Mithril pickaxe", + "level": 21 + }, + { + "item": "rs:adamant_pickaxe", + "text": "Adamant pickaxe", + "level": 31 + }, + { + "item": "rs:rune_pickaxe", + "text": "Rune pickaxe", + "level": 41 + } + ] + }, + { + "name": "Areas", + "lines": [ + { + "item": "rs:mithril_ore", + "text": "Mining guild", + "level": 60 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/prayer.json b/src/plugins/skills/skill-guides/prayer.json index ad745b74f..9a5d33838 100644 --- a/src/plugins/skills/skill-guides/prayer.json +++ b/src/plugins/skills/skill-guides/prayer.json @@ -3,151 +3,150 @@ "name": "Prayer", "members": false, "sub_guides": [ - { - "name": "Prayers", - "lines": [ - { - "item": "rs:prayer_guide", - "text": "While any of your prayers are active, your prayer\\n points will drain. Once you have run out of prayer\\n points, you will no longer be able to use prayers.\\n Visit an altar to recharge your prayer points.", - "level": "" - }, - { - "item": "rs:thick_skin", - "text": "Thick Skin", - "level": 1 - }, - { - "item": "rs:burst_of_strength", - "text": "Burst of Strength", - "level": 4 - }, - { - "item": "rs:clarity_of_thought", - "text": "Clariy of Thought", - "level": 7 - }, - { - "item": "rs:sharp_eye", - "text": "Sharp Eye", - "level": 8 - }, - { - "item": "rs:mystic_will", - "text": "Mystic Will", - "level": 9 - }, - { - "item": "rs:rock_skin", - "text": "Rock Skin", - "level": 10 - }, - { - "item": "rs:superhuman_strength", - "text": "Superhuman Strength", - "level": 13 - }, - { - "item": "rs:improved_reflexes", - "text": "Improved Reflexes", - "level": 16 - }, - { - "item": "rs:rapid_restore", - "text": "Rapid Restore", - "level": 19 - }, - { - "item": "rs:rapid_heal", - "text": "Rapid Heal", - "level": 22 - }, - { - "item": "rs:protect_item", - "text": "Protect Item", - "level": 25 - }, - { - "item": "rs:hawk_eye", - "text": "Hawk Eye", - "level": 26 - }, - { - "item": "rs:mystic_lore", - "text": "Mystical Lore", - "level": 27 - }, - { - "item": "rs:steel_skin", - "text": "Steel Skin", - "level": 28 - }, - { - "item": "rs:ultimate_strength", - "text": "Ultimate Strength", - "level": 31 - }, - { - "item": "rs:incredible_reflexes", - "text": "Incredible Reflexes", - "level": 34 - }, - { - "item": "rs:protect_from_magic", - "text": "Protect from Magic", - "level": 37 - }, - { - "item": "rs:protect_from_missiles", - "text": "Protect from Missiles", - "level": 40 - }, - { - "item": "rs:protect_from_melee", - "text": "Protect from Melee", - "level": 43 - }, - { - "item": "rs:eagle_eye", - "text": "Eagle Eye", - "level": 44 - }, - { - "item": "rs:mystic_might", - "text": "Mystic Might", - "level": 45 - }, - { - "item": "rs:retribution", - "text": "Members: Retribution", - "level": 46 - }, - { - "item": "rs:redemption", - "text": "Members: Redemption", - "level": 49 - }, - { - "item": "rs:smite", - "text": "Members: Smite", - "level": 52 - } - ] - }, - { - "name": "Equipment", - "lines": [ - { - "item": "rs:initate_full_helmet", - "text": "Initiate armour\\n(after Recruitment Drive, with\\nlevel 20 defence.", - "level": "10" - }, - { - "item": "rs:proselyte_full_helmet", - "text": "Proselyte armour\\n(after Slug Menace, with\\nlevel 30 defence.", - "level": "20" - } - ] - } + { + "name": "Prayers", + "lines": [ + { + "item": "rs:prayer_guide", + "text": "While any of your prayers are active, your prayer\\n points will drain. Once you have run out of prayer\\n points, you will no longer be able to use prayers.\\n Visit an altar to recharge your prayer points.", + "level": "" + }, + { + "item": "rs:thick_skin", + "text": "Thick Skin", + "level": 1 + }, + { + "item": "rs:burst_of_strength", + "text": "Burst of Strength", + "level": 4 + }, + { + "item": "rs:clarity_of_thought", + "text": "Clariy of Thought", + "level": 7 + }, + { + "item": "rs:sharp_eye", + "text": "Sharp Eye", + "level": 8 + }, + { + "item": "rs:mystic_will", + "text": "Mystic Will", + "level": 9 + }, + { + "item": "rs:rock_skin", + "text": "Rock Skin", + "level": 10 + }, + { + "item": "rs:superhuman_strength", + "text": "Superhuman Strength", + "level": 13 + }, + { + "item": "rs:improved_reflexes", + "text": "Improved Reflexes", + "level": 16 + }, + { + "item": "rs:rapid_restore", + "text": "Rapid Restore", + "level": 19 + }, + { + "item": "rs:rapid_heal", + "text": "Rapid Heal", + "level": 22 + }, + { + "item": "rs:protect_item", + "text": "Protect Item", + "level": 25 + }, + { + "item": "rs:hawk_eye", + "text": "Hawk Eye", + "level": 26 + }, + { + "item": "rs:mystic_lore", + "text": "Mystical Lore", + "level": 27 + }, + { + "item": "rs:steel_skin", + "text": "Steel Skin", + "level": 28 + }, + { + "item": "rs:ultimate_strength", + "text": "Ultimate Strength", + "level": 31 + }, + { + "item": "rs:incredible_reflexes", + "text": "Incredible Reflexes", + "level": 34 + }, + { + "item": "rs:protect_from_magic", + "text": "Protect from Magic", + "level": 37 + }, + { + "item": "rs:protect_from_missiles", + "text": "Protect from Missiles", + "level": 40 + }, + { + "item": "rs:protect_from_melee", + "text": "Protect from Melee", + "level": 43 + }, + { + "item": "rs:eagle_eye", + "text": "Eagle Eye", + "level": 44 + }, + { + "item": "rs:mystic_might", + "text": "Mystic Might", + "level": 45 + }, + { + "item": "rs:retribution", + "text": "Members: Retribution", + "level": 46 + }, + { + "item": "rs:redemption", + "text": "Members: Redemption", + "level": 49 + }, + { + "item": "rs:smite", + "text": "Members: Smite", + "level": 52 + } + ] + }, + { + "name": "Equipment", + "lines": [ + { + "item": "rs:initate_full_helmet", + "text": "Initiate armour\\n(after Recruitment Drive, with\\nlevel 20 defence.", + "level": "10" + }, + { + "item": "rs:proselyte_full_helmet", + "text": "Proselyte armour\\n(after Slug Menace, with\\nlevel 30 defence.", + "level": "20" + } + ] + } ] - } - \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/ranged.json b/src/plugins/skills/skill-guides/ranged.json index f3f6f8e76..8baafb2cc 100644 --- a/src/plugins/skills/skill-guides/ranged.json +++ b/src/plugins/skills/skill-guides/ranged.json @@ -1,272 +1,272 @@ { - "id": 127, - "name": "Ranged", - "members": false, - "sub_guides": [ - { - "name": "Bows", - "lines": [ - { - "item": "rs:standard_bow", - "text": "Standard bows\\n/Ammo: Arrows up to iron", - "level": 1 - }, - { - "item": "rs:oak_bow", - "text": "Oak bows\\nAmmo: Arrows up to steel", - "level": 5 - }, - { - "item": "rs:willow_bow", - "text": "Willow bows\\nAmmo: Arrows up to mithril", - "level": 20 - }, - { - "item": "rs:maple_bow", - "text": "Maple bows\\nAmmo: Arrows up to adamant", - "level": 30 - }, - { - "item": "rs:ogre_composite_bow", - "text": "Members: Ogre, composite bows\\nAmmo:'brutal' arrows up to rune", - "level": 30 - }, - { - "item": "rs:yew_bow", - "text": "Yew bows\\nAmmo: Arrows up to rune", - "level": 40 - }, - { - "item": "rs:magic_bow", - "text": "Magic bows\\nAmmo: Arrows up to rune", - "level": 50 - }, - { - "item": "rs:seercull_bow", - "text": "Members: Seercull bows\\nAmmo: Arrows up to rune", - "level": 50 - }, - { - "item": "rs:crystal_bow", - "text": "Members: Crystal bows (with 50 Agility)\\nAmmo: None", - "level": 70 - } - ] - }, - { - "name": "Thrown", - "lines": [ - { - "item": "rs:bronze_knife", - "text": "Bronze knifes\\nthrowing knifes", - "level": 1 - }, - { - "item": "rs:iron_knife", - "text": "Iron knifes\\nthrowing knifes", - "level": 1 - }, - { - "item": "rs:steel_knife", - "text": "Steel knifes\\nthrowing knifes", - "level": 5 - }, - { - "item": "rs:black_knife", - "text": "Black knifes\\nthrowing knifes", - "level": 10 - }, - { - "item": "rs:mithril_knife", - "text": "Mithril knifes\\nthrowing knifes", - "level": 20 - }, - { - "item": "rs:adamant_knife", - "text": "Adamant knifes\\nthrowing knifes)", - "level": 30 - }, - { - "item": "rs:rune_knife", - "text": "Rune knifes\\nthrowing knifes", - "level": 40 - }, - { - "item": "rs:toktz-xil-ul", - "text": "Toktz xil ul\\nobsidian throwing rings", - "level": 60 - } - ] - }, - { - "name": "Crossbows", - "lines": [ - { - "item": "rs:crossbow", - "text": "Crossbow\\nAmmo: Bronze crossbow bolts", - "level": 1 - }, - { - "item": "rs:phoenix_crossbow", - "text": "Phoenix crossbow\\nAmmo: Bronze crossbow bolts", - "level": 5 - }, - { - "item": "rs:bronze_crossbow", - "text": "Members: Crossbow\\nAmmo: Bronze crossbow bolts", - "level": 1 - }, - { - "item": "rs:blurite_crossbow", - "text": "Members: Blurite Crossbow\\nAmmo: bolts up to blurite", - "level": 16 - }, - { - "item": "rs:iron_crossbow", - "text": "Members: Crossbow\\nAmmo: Bolts up to iron", - "level": 26 - }, - { - "item": "rs:dorgeshuun_crossbow", - "text": "Members: Crossbow\\nAmmo: Bolts up to iron", - "level": 28 - }, - { - "item": "rs:steel_crossbow", - "text": "Members: Steel crossbow\\nAmmo: Bolts up to steel", - "level": 31 - }, - { - "item": "rs:mithril_crossbow", - "text": "Members: mithril crossbow\\nAmmo: Bolts up to mithril", - "level": 36 - }, - { - "item": "rs:adamant_crossbow", - "text": "Members: Adamant crossbow\\nAmmo: Bolts up to adamant", - "level": 46 - }, - { - "item": "rs:rune_crossbow", - "text": "Members: Rune crossbow\\nAmmo: Bolts up to rune", - "level": 61 - }, - { - "item": "rs:karils_crossbow", - "text": "Members: Karil's crossbow\\nAmmo: Bolt rack only", - "level": 70 - } - ] - }, - { - "name": "Armour", - "lines": [ - { - "item": "rs:plain_leather_items", - "text": "Plain leather items\\nwield any bronze equipment", - "level": 1 - }, - { - "item": "rs:hard_leather_body", - "text": "Hard leather body\\n(10 Defence required)", - "level": 5 - }, - { - "item": "rs:studded_leather_body", - "text": "Studded leather chaps\\n(20 Defence required)", - "level": 20 - }, - { - "item": "rs:studded_leather_chaps", - "text": "Studded leather chaps", - "level": 20 - }, - { - "item": "rs:coif", - "text": "Coif", - "level": 20 - }, - { - "item": "rs:snake_skin_armour", - "text": "Members: Snakeskin armour\\n(30 Defence required)", - "level": 30 - }, - { - "item": "rs:ranger_boots", - "text": "Ranger boots", - "level": 40 - }, - { - "item": "rs:robin_hood_hat", - "text": "Robin Hood hat", - "level": 40 - }, - { - "item": "rs:green_dragonhide_vambraces", - "text": "Members: Green dragonhide vambraces)", - "level": 40 - }, - { - "item": "rs:green_dragonhide_chaps", - "text": "Members: Proselyte armour)", - "level": 40 - }, - { - "item": "rs:green_dragonhide_body", - "text": "Green dragonhide body\\n(40 Defence required)", - "level": 30 - }, - { - "item": "rs:blue_dragonhide_vambraces", - "text": "Members: Blue dragonhide vambraces)", - "level": 50 - }, - { - "item": "rs:blue_dragonhide_chaps", - "text": "Members: Blue dragonhide chaps", - "level": 50 - }, - { - "item": "rs:blue_dragonhide_body", - "text": "Members: Blue dragonhide body\\n(40 Defence required)", - "level": 50 - }, - { - "item": "rs:red_dragonhide_vambraces", - "text": "Members: Red dragonhide vambraces)", - "level": 60 - }, - { - "item": "rs:red_dragonhide_chaps", - "text": "Members: Red dragonhide chaps)", - "level": 60 - }, - { - "item": "rs:red_dragonhide_body", - "text": "Members: Red dragonhide body\\n(40 Defence required)", - "level": 60 - }, - { - "item": "rs:black_dragonhide_vambraces", - "text": "Members: Black dragonhide vambraces)", - "level": 70 - }, - { - "item": "rs:black_dragonhide_chaps", - "text": "Members: Black dragonhide chaps)", - "level": 70 - }, - { - "item": "rs:black_dragonhide_body", - "text": "Members: Black dragonhide body\\n(40 Defence required)", - "level": 70 - }, - { - "item": "rs:karils_leathertop", - "text": "Members: Karil's leather armour\\(70 Defence required)", - "level": 70 + "id": 127, + "name": "Ranged", + "members": false, + "sub_guides": [ + { + "name": "Bows", + "lines": [ + { + "item": "rs:standard_bow", + "text": "Standard bows\\n/Ammo: Arrows up to iron", + "level": 1 + }, + { + "item": "rs:oak_bow", + "text": "Oak bows\\nAmmo: Arrows up to steel", + "level": 5 + }, + { + "item": "rs:willow_bow", + "text": "Willow bows\\nAmmo: Arrows up to mithril", + "level": 20 + }, + { + "item": "rs:maple_bow", + "text": "Maple bows\\nAmmo: Arrows up to adamant", + "level": 30 + }, + { + "item": "rs:ogre_composite_bow", + "text": "Members: Ogre, composite bows\\nAmmo:'brutal' arrows up to rune", + "level": 30 + }, + { + "item": "rs:yew_bow", + "text": "Yew bows\\nAmmo: Arrows up to rune", + "level": 40 + }, + { + "item": "rs:magic_bow", + "text": "Magic bows\\nAmmo: Arrows up to rune", + "level": 50 + }, + { + "item": "rs:seercull_bow", + "text": "Members: Seercull bows\\nAmmo: Arrows up to rune", + "level": 50 + }, + { + "item": "rs:crystal_bow", + "text": "Members: Crystal bows (with 50 Agility)\\nAmmo: None", + "level": 70 + } + ] + }, + { + "name": "Thrown", + "lines": [ + { + "item": "rs:bronze_knife", + "text": "Bronze knifes\\nthrowing knifes", + "level": 1 + }, + { + "item": "rs:iron_knife", + "text": "Iron knifes\\nthrowing knifes", + "level": 1 + }, + { + "item": "rs:steel_knife", + "text": "Steel knifes\\nthrowing knifes", + "level": 5 + }, + { + "item": "rs:black_knife", + "text": "Black knifes\\nthrowing knifes", + "level": 10 + }, + { + "item": "rs:mithril_knife", + "text": "Mithril knifes\\nthrowing knifes", + "level": 20 + }, + { + "item": "rs:adamant_knife", + "text": "Adamant knifes\\nthrowing knifes)", + "level": 30 + }, + { + "item": "rs:rune_knife", + "text": "Rune knifes\\nthrowing knifes", + "level": 40 + }, + { + "item": "rs:toktz-xil-ul", + "text": "Toktz xil ul\\nobsidian throwing rings", + "level": 60 + } + ] + }, + { + "name": "Crossbows", + "lines": [ + { + "item": "rs:crossbow", + "text": "Crossbow\\nAmmo: Bronze crossbow bolts", + "level": 1 + }, + { + "item": "rs:phoenix_crossbow", + "text": "Phoenix crossbow\\nAmmo: Bronze crossbow bolts", + "level": 5 + }, + { + "item": "rs:bronze_crossbow", + "text": "Members: Crossbow\\nAmmo: Bronze crossbow bolts", + "level": 1 + }, + { + "item": "rs:blurite_crossbow", + "text": "Members: Blurite Crossbow\\nAmmo: bolts up to blurite", + "level": 16 + }, + { + "item": "rs:iron_crossbow", + "text": "Members: Crossbow\\nAmmo: Bolts up to iron", + "level": 26 + }, + { + "item": "rs:dorgeshuun_crossbow", + "text": "Members: Crossbow\\nAmmo: Bolts up to iron", + "level": 28 + }, + { + "item": "rs:steel_crossbow", + "text": "Members: Steel crossbow\\nAmmo: Bolts up to steel", + "level": 31 + }, + { + "item": "rs:mithril_crossbow", + "text": "Members: mithril crossbow\\nAmmo: Bolts up to mithril", + "level": 36 + }, + { + "item": "rs:adamant_crossbow", + "text": "Members: Adamant crossbow\\nAmmo: Bolts up to adamant", + "level": 46 + }, + { + "item": "rs:rune_crossbow", + "text": "Members: Rune crossbow\\nAmmo: Bolts up to rune", + "level": 61 + }, + { + "item": "rs:karils_crossbow", + "text": "Members: Karil's crossbow\\nAmmo: Bolt rack only", + "level": 70 + } + ] + }, + { + "name": "Armour", + "lines": [ + { + "item": "rs:plain_leather_items", + "text": "Plain leather items\\nwield any bronze equipment", + "level": 1 + }, + { + "item": "rs:hard_leather_body", + "text": "Hard leather body\\n(10 Defence required)", + "level": 5 + }, + { + "item": "rs:studded_leather_body", + "text": "Studded leather chaps\\n(20 Defence required)", + "level": 20 + }, + { + "item": "rs:studded_leather_chaps", + "text": "Studded leather chaps", + "level": 20 + }, + { + "item": "rs:coif", + "text": "Coif", + "level": 20 + }, + { + "item": "rs:snake_skin_armour", + "text": "Members: Snakeskin armour\\n(30 Defence required)", + "level": 30 + }, + { + "item": "rs:ranger_boots", + "text": "Ranger boots", + "level": 40 + }, + { + "item": "rs:robin_hood_hat", + "text": "Robin Hood hat", + "level": 40 + }, + { + "item": "rs:green_dragonhide_vambraces", + "text": "Members: Green dragonhide vambraces)", + "level": 40 + }, + { + "item": "rs:green_dragonhide_chaps", + "text": "Members: Proselyte armour)", + "level": 40 + }, + { + "item": "rs:green_dragonhide_body", + "text": "Green dragonhide body\\n(40 Defence required)", + "level": 30 + }, + { + "item": "rs:blue_dragonhide_vambraces", + "text": "Members: Blue dragonhide vambraces)", + "level": 50 + }, + { + "item": "rs:blue_dragonhide_chaps", + "text": "Members: Blue dragonhide chaps", + "level": 50 + }, + { + "item": "rs:blue_dragonhide_body", + "text": "Members: Blue dragonhide body\\n(40 Defence required)", + "level": 50 + }, + { + "item": "rs:red_dragonhide_vambraces", + "text": "Members: Red dragonhide vambraces)", + "level": 60 + }, + { + "item": "rs:red_dragonhide_chaps", + "text": "Members: Red dragonhide chaps)", + "level": 60 + }, + { + "item": "rs:red_dragonhide_body", + "text": "Members: Red dragonhide body\\n(40 Defence required)", + "level": 60 + }, + { + "item": "rs:black_dragonhide_vambraces", + "text": "Members: Black dragonhide vambraces)", + "level": 70 + }, + { + "item": "rs:black_dragonhide_chaps", + "text": "Members: Black dragonhide chaps)", + "level": 70 + }, + { + "item": "rs:black_dragonhide_body", + "text": "Members: Black dragonhide body\\n(40 Defence required)", + "level": 70 + }, + { + "item": "rs:karils_leathertop", + "text": "Members: Karil's leather armour\\(70 Defence required)", + "level": 70 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/runecrafting.json b/src/plugins/skills/skill-guides/runecrafting.json index 90436ea67..a344d54b6 100644 --- a/src/plugins/skills/skill-guides/runecrafting.json +++ b/src/plugins/skills/skill-guides/runecrafting.json @@ -1,312 +1,312 @@ { - "id": 140, - "name": "Runecrafting", - "members": false, - "sub_guides": [ - { - "name": "Runes", - "lines": [ - { - "item": "rs:air_rune", - "text": "Air runes", - "level": 1 - }, - { - "item": "rs:mind_rune", - "text": "Mind runes", - "level": 2 - }, - { - "item": "rs:water_rune", - "text": "Water runes", - "level": 5 - }, - { - "item": "rs:mist_rune", - "text": "Members: Mist runes", - "level": 6 - }, - { - "item": "rs:earth_rune", - "text": "Earth runes", - "level": 9 - }, - { - "item": "rs:dust_rune", - "text": "Members: Dust runes", - "level": 10 - }, - { - "item": "rs:mud_rune", - "text": "Members: Mud runes", - "level": 13 - }, - { - "item": "rs:fire_rune", - "text": "Fire runes", - "level": 14 - }, - { - "item": "rs:smoke_rune", - "text": "Members: Smoke runes", - "level": 15 - }, - { - "item": "rs:steam_rune", - "text": "Members: Steam runes", - "level": 19 - }, - { - "item": "rs:body_rune", - "text": "Body runes", - "level": 20 - }, - { - "item": "rs:lava_rune", - "text": "Members: Lava runes", - "level": 23 - }, - { - "item": "rs:cosmic_rune", - "text": "Members: Cosmic runes", - "level": 27 - }, - { - "item": "rs:chaos_rune", - "text": "Members: Chaos runes", - "level": 35 - }, - { - "item": "rs:astral_rune", - "text": "Members: Astral runes", - "level": 40 - }, - { - "item": "rs:nature_rune", - "text": "Members: Nature runes", - "level": 44 - }, - { - "item": "rs:law_rune", - "text": "Members: Law runes", - "level": 54 - }, - { - "item": "rs:death_rune", - "text": "Members: Death runes", - "level": 65 - }, - { - "item": "rs:blood_rune", - "text": "Members: Blood runes", - "level": 77 - }, - { - "item": "rs:soul_rune", - "text": "Members: Soul runes", - "level": 90 - } - ] - }, - { - "name": "Multiple", - "lines": [ - { - "item": "rs:air_rune", - "text": "2 Air runes per essence", - "level": 11 - }, - { - "item": "rs:mind_rune", - "text": "2 Mind runes per essence", - "level": 14 - }, - { - "item": "rs:water_rune", - "text": "2 Water runes per essence", - "level": 19 - }, - { - "item": "rs:air_rune", - "text": "3 Air runes per essence", - "level": 22 - }, - { - "item": "rs:earth_rune", - "text": "2 Earth runes per essence", - "level": 26 - }, - { - "item": "rs:mind_rune", - "text": "3 Mind runes per essence", - "level": 28 - }, - { - "item": "rs:air_rune", - "text": "4 Air runes per essence", - "level": 33 - }, - { - "item": "rs:fire_rune", - "text": "2 Fire runes per essence", - "level": 35 - }, - { - "item": "rs:water_rune", - "text": "3 Water runes per essence", - "level": 38 - }, - { - "item": "rs:mind_rune", - "text": "4 Mind runes per essence", - "level": 42 - }, - { - "item": "rs:air_rune", - "text": "5 Air runes per essence", - "level": 44 - }, - { - "item": "rs:body_rune", - "text": "2 Body runes per essence", - "level": 46 - }, - { - "item": "rs:earth_rune", - "text": "3 Earth runes per essence", - "level": 52 - }, - { - "item": "rs:air_rune", - "text": "6 Air runes per essence", - "level": 55 - }, - { - "item": "rs:mind_rune", - "text": "5 Mind runes per essence", - "level": 56 - }, - { - "item": "rs:water_rune", - "text": "4 Water runes per essence", - "level": 57 - }, - { - "item": "rs:cosmic_rune", - "text": "Members: 2 Cosmic runes per essence", - "level": 59 - }, - { - "item": "rs:air_rune", - "text": "7 Air runes per essence", - "level": 66 - }, - { - "item": "rs:mind_rune", - "text": "6 Mind runes per essence", - "level": 70 - }, - { - "item": "rs:fire_rune", - "text": "3 Fire runes per essence", - "level": 70 - }, - { - "item": "rs:chaos_rune", - "text": "Members: 2 Chaos runes per essence", - "level": 74 - }, - { - "item": "rs:water_rune", - "text": "5 Water runes per essence", - "level": 76 - }, - { - "item": "rs:air_rune", - "text": "8 Air runes per essence", - "level": 77 - }, - { - "item": "rs:earth_rune", - "text": "4 Earth runes per essence", - "level": 78 - }, - { - "item": "rs:astral_rune", - "text": "Members: 2 Astral runes per essence", - "level": 82 - }, - { - "item": "rs:mind_rune", - "text": "7 Mind runes per essence", - "level": 84 - }, - { - "item": "rs:air_rune", - "text": "9 Air runes per essence", - "level": 88 - }, - { - "item": "rs:nature_rune", - "text": "Members: 2 Nature runes per essence", - "level": 91 - }, - { - "item": "rs:body_rune", - "text": "3 Body runes per essence", - "level": 92 - }, - { - "item_id": "rs:water_rune", - "text": "6 Water runes per essence", - "level": 95 - }, - { - "item": "rs:law_rune", - "text": "Members: 2 Law runes per essence", - "level": 95 - }, - { - "item": "rs:mind_rune", - "text": "8 Mind runes per essence", - "level": 98 - }, - { - "item": "rs:air_rune", - "text": "10 Air runes per essence", - "level": 99 - }, - { - "item": "rs:death_rune", - "text": "Members: 2 Death runes per essence", - "level": 99 - } - ] - }, - { - "name": "Pouches", - "lines": [ - { - "item": "rs:small_pouch", - "text": "Small pouch: Holds 3 extra essence", - "level": 1 - }, - { - "item": "rs:medium_pouch", - "text": "Medium pouch: Holds 6 extra essence", - "level": 25 - }, - { - "item": "rs:large_pouch", - "text": "Large pouch: Holds 9 extra essence", - "level": 50 - }, - { - "item": "rs:giant_pouch", - "text": "Giant pouch: Holds 12 extra essence", - "level": 75 + "id": 140, + "name": "Runecrafting", + "members": false, + "sub_guides": [ + { + "name": "Runes", + "lines": [ + { + "item": "rs:air_rune", + "text": "Air runes", + "level": 1 + }, + { + "item": "rs:mind_rune", + "text": "Mind runes", + "level": 2 + }, + { + "item": "rs:water_rune", + "text": "Water runes", + "level": 5 + }, + { + "item": "rs:mist_rune", + "text": "Members: Mist runes", + "level": 6 + }, + { + "item": "rs:earth_rune", + "text": "Earth runes", + "level": 9 + }, + { + "item": "rs:dust_rune", + "text": "Members: Dust runes", + "level": 10 + }, + { + "item": "rs:mud_rune", + "text": "Members: Mud runes", + "level": 13 + }, + { + "item": "rs:fire_rune", + "text": "Fire runes", + "level": 14 + }, + { + "item": "rs:smoke_rune", + "text": "Members: Smoke runes", + "level": 15 + }, + { + "item": "rs:steam_rune", + "text": "Members: Steam runes", + "level": 19 + }, + { + "item": "rs:body_rune", + "text": "Body runes", + "level": 20 + }, + { + "item": "rs:lava_rune", + "text": "Members: Lava runes", + "level": 23 + }, + { + "item": "rs:cosmic_rune", + "text": "Members: Cosmic runes", + "level": 27 + }, + { + "item": "rs:chaos_rune", + "text": "Members: Chaos runes", + "level": 35 + }, + { + "item": "rs:astral_rune", + "text": "Members: Astral runes", + "level": 40 + }, + { + "item": "rs:nature_rune", + "text": "Members: Nature runes", + "level": 44 + }, + { + "item": "rs:law_rune", + "text": "Members: Law runes", + "level": 54 + }, + { + "item": "rs:death_rune", + "text": "Members: Death runes", + "level": 65 + }, + { + "item": "rs:blood_rune", + "text": "Members: Blood runes", + "level": 77 + }, + { + "item": "rs:soul_rune", + "text": "Members: Soul runes", + "level": 90 + } + ] + }, + { + "name": "Multiple", + "lines": [ + { + "item": "rs:air_rune", + "text": "2 Air runes per essence", + "level": 11 + }, + { + "item": "rs:mind_rune", + "text": "2 Mind runes per essence", + "level": 14 + }, + { + "item": "rs:water_rune", + "text": "2 Water runes per essence", + "level": 19 + }, + { + "item": "rs:air_rune", + "text": "3 Air runes per essence", + "level": 22 + }, + { + "item": "rs:earth_rune", + "text": "2 Earth runes per essence", + "level": 26 + }, + { + "item": "rs:mind_rune", + "text": "3 Mind runes per essence", + "level": 28 + }, + { + "item": "rs:air_rune", + "text": "4 Air runes per essence", + "level": 33 + }, + { + "item": "rs:fire_rune", + "text": "2 Fire runes per essence", + "level": 35 + }, + { + "item": "rs:water_rune", + "text": "3 Water runes per essence", + "level": 38 + }, + { + "item": "rs:mind_rune", + "text": "4 Mind runes per essence", + "level": 42 + }, + { + "item": "rs:air_rune", + "text": "5 Air runes per essence", + "level": 44 + }, + { + "item": "rs:body_rune", + "text": "2 Body runes per essence", + "level": 46 + }, + { + "item": "rs:earth_rune", + "text": "3 Earth runes per essence", + "level": 52 + }, + { + "item": "rs:air_rune", + "text": "6 Air runes per essence", + "level": 55 + }, + { + "item": "rs:mind_rune", + "text": "5 Mind runes per essence", + "level": 56 + }, + { + "item": "rs:water_rune", + "text": "4 Water runes per essence", + "level": 57 + }, + { + "item": "rs:cosmic_rune", + "text": "Members: 2 Cosmic runes per essence", + "level": 59 + }, + { + "item": "rs:air_rune", + "text": "7 Air runes per essence", + "level": 66 + }, + { + "item": "rs:mind_rune", + "text": "6 Mind runes per essence", + "level": 70 + }, + { + "item": "rs:fire_rune", + "text": "3 Fire runes per essence", + "level": 70 + }, + { + "item": "rs:chaos_rune", + "text": "Members: 2 Chaos runes per essence", + "level": 74 + }, + { + "item": "rs:water_rune", + "text": "5 Water runes per essence", + "level": 76 + }, + { + "item": "rs:air_rune", + "text": "8 Air runes per essence", + "level": 77 + }, + { + "item": "rs:earth_rune", + "text": "4 Earth runes per essence", + "level": 78 + }, + { + "item": "rs:astral_rune", + "text": "Members: 2 Astral runes per essence", + "level": 82 + }, + { + "item": "rs:mind_rune", + "text": "7 Mind runes per essence", + "level": 84 + }, + { + "item": "rs:air_rune", + "text": "9 Air runes per essence", + "level": 88 + }, + { + "item": "rs:nature_rune", + "text": "Members: 2 Nature runes per essence", + "level": 91 + }, + { + "item": "rs:body_rune", + "text": "3 Body runes per essence", + "level": 92 + }, + { + "item_id": "rs:water_rune", + "text": "6 Water runes per essence", + "level": 95 + }, + { + "item": "rs:law_rune", + "text": "Members: 2 Law runes per essence", + "level": 95 + }, + { + "item": "rs:mind_rune", + "text": "8 Mind runes per essence", + "level": 98 + }, + { + "item": "rs:air_rune", + "text": "10 Air runes per essence", + "level": 99 + }, + { + "item": "rs:death_rune", + "text": "Members: 2 Death runes per essence", + "level": 99 + } + ] + }, + { + "name": "Pouches", + "lines": [ + { + "item": "rs:small_pouch", + "text": "Small pouch: Holds 3 extra essence", + "level": 1 + }, + { + "item": "rs:medium_pouch", + "text": "Medium pouch: Holds 6 extra essence", + "level": 25 + }, + { + "item": "rs:large_pouch", + "text": "Large pouch: Holds 9 extra essence", + "level": 50 + }, + { + "item": "rs:giant_pouch", + "text": "Giant pouch: Holds 12 extra essence", + "level": 75 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/skill-guide-config.ts b/src/plugins/skills/skill-guides/skill-guide-config.ts index 263d5875a..3fb1e5890 100644 --- a/src/plugins/skills/skill-guides/skill-guide-config.ts +++ b/src/plugins/skills/skill-guides/skill-guide-config.ts @@ -41,24 +41,24 @@ export async function loadSkillGuideConfigurations(path: string): Promise(path); - files.forEach((skillGuide) => { - if(!skillGuide?.sub_guides) { + files.forEach(skillGuide => { + if (!skillGuide?.sub_guides) { return; } const subGuides: SkillSubGuide[] = []; - skillGuide.sub_guides.forEach((subGuide) => { + skillGuide.sub_guides.forEach(subGuide => { const subGuideLines: SkillSubGuide['lines'] = []; - subGuide.lines.forEach((line) => { + subGuide.lines.forEach(line => { subGuideLines.push({ item: itemMap[line.item], text: line.text, - level: line.level + level: line.level, }); }); subGuides.push({ name: subGuide.name, - lines: subGuideLines + lines: subGuideLines, }); }); skillGuides.push({ diff --git a/src/plugins/skills/skill-guides/skill-guides.plugin.ts b/src/plugins/skills/skill-guides/skill-guides.plugin.ts index 67dd001df..9a0b08d8c 100644 --- a/src/plugins/skills/skill-guides/skill-guides.plugin.ts +++ b/src/plugins/skills/skill-guides/skill-guides.plugin.ts @@ -1,11 +1,10 @@ -import type { buttonActionHandler, ButtonActionHook } from '@engine/action/pipe/button.action'; -import type { widgetInteractionActionHandler, WidgetInteractionActionHook } from '@engine/action/pipe/widget-interaction.action'; +import type { ButtonActionHook, buttonActionHandler } from '@engine/action/pipe/button.action'; +import type { WidgetInteractionActionHook, widgetInteractionActionHandler } from '@engine/action/pipe/widget-interaction.action'; import { widgets } from '@engine/config/config-handler'; import type { Player } from '@engine/world/actor/player/player'; +import { logger } from '@runejs/common'; import type { SkillGuide, SkillSubGuide } from './skill-guide-config'; import { loadSkillGuideConfigurations } from './skill-guide-config'; -import { logger } from '@runejs/common'; - const skillGuidePath = __dirname.replace(/dist/, 'src'); const sidebarTextIds = [131, 108, 109, 112, 122, 125, 128, 143, 146, 149, 159, 162, 165]; @@ -20,14 +19,14 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr return; } - if(refreshSidebar) { - player.modifyWidget(widgets.skillGuide, { childId: 133, text: (guide.members ? 'Members only skill' : '') }); + if (refreshSidebar) { + player.modifyWidget(widgets.skillGuide, { childId: 133, text: guide.members ? 'Members only skill' : '' }); - for(let i = 0; i < sidebarTextIds.length; i++) { + for (let i = 0; i < sidebarTextIds.length; i++) { const sidebarId = sidebarIds[i]; let hidden: boolean = true; - if(i >= guide.sub_guides.length) { + if (i >= guide.sub_guides.length) { player.modifyWidget(widgets.skillGuide, { childId: sidebarTextIds[i], text: '' }); hidden = true; } else { @@ -35,7 +34,7 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr hidden = false; } - if(sidebarId !== -1) { + if (sidebarId !== -1) { // Apparently you can never have only TWO subguides... // Because childId 98 deletes both options 2 AND 3. So, good thing there are no guides with only 2 sections, I guess?... // Verified this in an interface editor, and they are indeed grouped in a single layer for some reason... @@ -46,13 +45,13 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr const subGuide: SkillSubGuide = guide.sub_guides[subGuideId]; - player.modifyWidget(widgets.skillGuide, { childId: 1, text: (guide.name + ' - ' + subGuide.name) }); + player.modifyWidget(widgets.skillGuide, { childId: 1, text: guide.name + ' - ' + subGuide.name }); - const itemIds: number[] = subGuide.lines.map(g => (g.item?.gameId || 0)).concat(new Array(30 - subGuide.lines.length).fill(null)); + const itemIds: number[] = subGuide.lines.map(g => g.item?.gameId || 0).concat(new Array(30 - subGuide.lines.length).fill(null)); player.outgoingPackets.sendUpdateAllWidgetItemsById({ widgetId: widgets.skillGuide, containerId: 132 }, itemIds); - for(let i = 0; i < 30; i++) { - if(subGuide.lines.length <= i) { + for (let i = 0; i < 30; i++) { + if (subGuide.lines.length <= i) { player.modifyWidget(widgets.skillGuide, { childId: 5 + i, text: '' }); player.modifyWidget(widgets.skillGuide, { childId: 45 + i, text: '' }); } else { @@ -63,31 +62,31 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr player.interfaceState.openWidget(widgets.skillGuide, { slot: 'screen', - multi: false + multi: false, }); player.metadata.activeSkillGuide = guideId; } -export const guideHandler: buttonActionHandler = async (details) => { +export const guideHandler: buttonActionHandler = async details => { const { player, buttonId } = details; - if(!guides.length) { + if (!guides.length) { guides = await loadSkillGuideConfigurations(skillGuidePath); } loadGuide(player, buttonId); }; -export const subGuideHandler: widgetInteractionActionHandler = async (details) => { +export const subGuideHandler: widgetInteractionActionHandler = async details => { const { player, childId } = details; - if(!guides.length) { + if (!guides.length) { guides = await loadSkillGuideConfigurations(skillGuidePath); } const activeSkillGuide = player.metadata.activeSkillGuide; - if(!activeSkillGuide) { + if (!activeSkillGuide) { return; } @@ -100,7 +99,7 @@ export const subGuideHandler: widgetInteractionActionHandler = async (details) = const subGuideId = sidebarTextIds.indexOf(childId); - if(subGuideId >= guide.sub_guides.length) { + if (subGuideId >= guide.sub_guides.length) { return; } @@ -113,13 +112,13 @@ export default { { type: 'button', widgetId: widgets.skillsTab, - handler: guideHandler + handler: guideHandler, } as ButtonActionHook, { type: 'widget_interaction', widgetIds: widgets.skillGuide, optionId: 0, - handler: subGuideHandler - } as WidgetInteractionActionHook - ] + handler: subGuideHandler, + } as WidgetInteractionActionHook, + ], }; diff --git a/src/plugins/skills/skill-guides/slayer.json b/src/plugins/skills/skill-guides/slayer.json index 6f2c53bff..f6adff809 100644 --- a/src/plugins/skills/skill-guides/slayer.json +++ b/src/plugins/skills/skill-guides/slayer.json @@ -3,269 +3,270 @@ "name": "Slayer", "members": false, "sub_guides": [ - { - "name": "Monsters", - "lines": [ - { - "item": "rs:crawling_hands", - "text": "Crawling hands", - "level": 5 - }, - { - "item": "rs:cave_bugs", - "text": "Cave bugs", - "level": 7 - }, - { - "item": "rs:cave_crawlers", - "text": "Cave crawlers", - "level": 10 - }, - { - "item": "rs:Banshees", - "text": "banshees", - "level": 15 - }, - { - "item": "rs:cave_slime", - "text": "Cave slime", - "level": 17 - }, - { - "item": "rs:rockslugs", - "text": "Rockslugs", - "level": 20 - }, - { - "item": "rs:desert_lizards", - "text": "Desert lizards", - "level": 22 - }, - { - "item": "rs:cockatrice", - "text": "Cockatrice", - "level": 25 - }, - { - "item": "rs:pyrefiends", - "text": "Pyrefiends", - "level": 30 - }, - { - "item": "rs:mogres", - "text": "Mogres", - "level": 32 - }, - { - "item": "rs:harpie_bug_swarms", - "text": "Harpie bug swarms", - "level": 33 - }, - { - "item": "rs:wall_beasts", - "text": "Wall beasts", - "level": 35 - }, - { - "item": "rs:killerwatts", - "text": "Killerwatts", - "level": 37 - }, - { - "item": "rs:basilisks", - "text": "Basilisks", - "level": 40 - }, - { - "item": "rs:fever_spiders", - "text": "Fever spiders", - "level": 42 - }, - { - "item": "rs:infernal_mages", - "text": "Infernal mages", - "level": 45 - }, - { - "item": "rs:brine_rats", - "text": "Brine rats", - "level": 47 - }, - { - "item": "rs:bloodvelds", - "text": "Bloodvelds", - "level": 50 - }, - { - "item": "rs:jellies", - "text": "Jellies", - "level": 52 - }, - { - "item": "rs:turoth", - "text": "Turoth", - "level": 55 - }, - { - "item": "rs:cave_horrors", - "text": "Cave horrors", - "level": 58 - }, - { - "item": "rs:aberrant_spectres", - "text": "Aberrant spectres", - "level": 60 - }, - { - "item": "rs:dust_devils", - "text": "Dust devils", - "level": 65 - }, - { - "item": "rs:kurask", - "text": "Kurask", - "level": 70 - }, - { - "item": "rs:skeletal_wyverns", - "text": "Skeletal wyverns", - "level": 72 - }, - { - "item": "rs:gargoyles", - "text": "Gargoyles", - "level": 75 - }, - { - "item": "rs:nechryael", - "text": "Nechryael", - "level": 80 - }, - { - "item": "rs:abyssal demons", - "text": "Abyssal demons", - "level": 85 - }, - { - "item": "rs:dark_beasts", - "text": "Dark beasts", - "level": 58 - } - ] - }, { - "name": "Equipment", - "lines": [ - { - "item": "rs:spiny_helmet", - "text": "Spiney helmet\\n(5 Defence required)", - "level": 1 - }, - { - "item": "rs:rock_hammer", - "text": "Rock hammer & Rock Thrownhammer", - "level": 1 - }, - { - "item": "rs:facemask", - "text": "Facemask", - "level": 10 - }, - { - "item": "rs:earmuffs", - "text": "Earmuffs", - "level": 15 - }, - { - "item": "rs:mirror_shield", - "text": "Mirror shield\\n(20 Defence required)", - "level": 25 - }, - { - "item": "rs:harpie_bug_lantern", - "text": "Harpie bug lantern\\n(not a light source)", - "level": 33 - }, - { - "item": "rs:witchwood_icon", - "text": "Witchwood icon", - "level": 35 - }, - { - "item": "rs:insulated_boots", - "text": "Insultated boots", - "level": 37 - }, - { - "item": "rs:slayer_bell", - "text": "Slayer bell", - "level": 39 - }, - { - "item": "rs:slayer_gloves", - "text": "Slayer gloves", - "level": 42 - }, - { - "item": "rs:boots_of_stone", - "text": "Boots of Stone", - "level": 44 - }, - { - "item": "rs:leaf_bladed_spear", - "text": "Leafbladed spear\\n(50 Attack required)", - "level": 55 - }, - { - "item": "rs:broad_arrows", - "text": "Broad arrows\\n(50 Ranged required)", - "level": 55 - }, - { - "item": "rs:slayer_staff", - "text": "Slayer's staff\\n(50 Magic required)", - "level": 55 - }, - { - "item": "rs:fungicide_spray", - "text": "Fungicide spray", - "level": 57 - }, - { - "item": "rs:nose_peg", - "text": "Nose peg", - "level": 60 - } - ] - },{ - "name": "Slayer Masters", - "lines": [ - { - "item": "rs:enchanted_gem", - "text": "Burthorpe master\\n(Level 3 combat required)", - "level": 1 - }, - { - "item": "rs:enchanted_gem", - "text": "Canifis master\\n(Level 20 combat required)", - "level": 1 - }, { - "item": "rs:enchanted_gem", - "text": "Edgeville Dungeon master\\n(Level 40 combat required)", - "level": 1 - }, - { - "item": "rs:enchanted_gem", - "text": "Zanaris master\\n(Level 70 combat required)", - "level": 1 - }, - { - "item": "rs:enchanted_gem", - "text": "Shilo Village master\\n(Level 100 combat required)", - "level": 50 - } - - ] - } + { + "name": "Monsters", + "lines": [ + { + "item": "rs:crawling_hands", + "text": "Crawling hands", + "level": 5 + }, + { + "item": "rs:cave_bugs", + "text": "Cave bugs", + "level": 7 + }, + { + "item": "rs:cave_crawlers", + "text": "Cave crawlers", + "level": 10 + }, + { + "item": "rs:Banshees", + "text": "banshees", + "level": 15 + }, + { + "item": "rs:cave_slime", + "text": "Cave slime", + "level": 17 + }, + { + "item": "rs:rockslugs", + "text": "Rockslugs", + "level": 20 + }, + { + "item": "rs:desert_lizards", + "text": "Desert lizards", + "level": 22 + }, + { + "item": "rs:cockatrice", + "text": "Cockatrice", + "level": 25 + }, + { + "item": "rs:pyrefiends", + "text": "Pyrefiends", + "level": 30 + }, + { + "item": "rs:mogres", + "text": "Mogres", + "level": 32 + }, + { + "item": "rs:harpie_bug_swarms", + "text": "Harpie bug swarms", + "level": 33 + }, + { + "item": "rs:wall_beasts", + "text": "Wall beasts", + "level": 35 + }, + { + "item": "rs:killerwatts", + "text": "Killerwatts", + "level": 37 + }, + { + "item": "rs:basilisks", + "text": "Basilisks", + "level": 40 + }, + { + "item": "rs:fever_spiders", + "text": "Fever spiders", + "level": 42 + }, + { + "item": "rs:infernal_mages", + "text": "Infernal mages", + "level": 45 + }, + { + "item": "rs:brine_rats", + "text": "Brine rats", + "level": 47 + }, + { + "item": "rs:bloodvelds", + "text": "Bloodvelds", + "level": 50 + }, + { + "item": "rs:jellies", + "text": "Jellies", + "level": 52 + }, + { + "item": "rs:turoth", + "text": "Turoth", + "level": 55 + }, + { + "item": "rs:cave_horrors", + "text": "Cave horrors", + "level": 58 + }, + { + "item": "rs:aberrant_spectres", + "text": "Aberrant spectres", + "level": 60 + }, + { + "item": "rs:dust_devils", + "text": "Dust devils", + "level": 65 + }, + { + "item": "rs:kurask", + "text": "Kurask", + "level": 70 + }, + { + "item": "rs:skeletal_wyverns", + "text": "Skeletal wyverns", + "level": 72 + }, + { + "item": "rs:gargoyles", + "text": "Gargoyles", + "level": 75 + }, + { + "item": "rs:nechryael", + "text": "Nechryael", + "level": 80 + }, + { + "item": "rs:abyssal demons", + "text": "Abyssal demons", + "level": 85 + }, + { + "item": "rs:dark_beasts", + "text": "Dark beasts", + "level": 58 + } + ] + }, + { + "name": "Equipment", + "lines": [ + { + "item": "rs:spiny_helmet", + "text": "Spiney helmet\\n(5 Defence required)", + "level": 1 + }, + { + "item": "rs:rock_hammer", + "text": "Rock hammer & Rock Thrownhammer", + "level": 1 + }, + { + "item": "rs:facemask", + "text": "Facemask", + "level": 10 + }, + { + "item": "rs:earmuffs", + "text": "Earmuffs", + "level": 15 + }, + { + "item": "rs:mirror_shield", + "text": "Mirror shield\\n(20 Defence required)", + "level": 25 + }, + { + "item": "rs:harpie_bug_lantern", + "text": "Harpie bug lantern\\n(not a light source)", + "level": 33 + }, + { + "item": "rs:witchwood_icon", + "text": "Witchwood icon", + "level": 35 + }, + { + "item": "rs:insulated_boots", + "text": "Insultated boots", + "level": 37 + }, + { + "item": "rs:slayer_bell", + "text": "Slayer bell", + "level": 39 + }, + { + "item": "rs:slayer_gloves", + "text": "Slayer gloves", + "level": 42 + }, + { + "item": "rs:boots_of_stone", + "text": "Boots of Stone", + "level": 44 + }, + { + "item": "rs:leaf_bladed_spear", + "text": "Leafbladed spear\\n(50 Attack required)", + "level": 55 + }, + { + "item": "rs:broad_arrows", + "text": "Broad arrows\\n(50 Ranged required)", + "level": 55 + }, + { + "item": "rs:slayer_staff", + "text": "Slayer's staff\\n(50 Magic required)", + "level": 55 + }, + { + "item": "rs:fungicide_spray", + "text": "Fungicide spray", + "level": 57 + }, + { + "item": "rs:nose_peg", + "text": "Nose peg", + "level": 60 + } + ] + }, + { + "name": "Slayer Masters", + "lines": [ + { + "item": "rs:enchanted_gem", + "text": "Burthorpe master\\n(Level 3 combat required)", + "level": 1 + }, + { + "item": "rs:enchanted_gem", + "text": "Canifis master\\n(Level 20 combat required)", + "level": 1 + }, + { + "item": "rs:enchanted_gem", + "text": "Edgeville Dungeon master\\n(Level 40 combat required)", + "level": 1 + }, + { + "item": "rs:enchanted_gem", + "text": "Zanaris master\\n(Level 70 combat required)", + "level": 1 + }, + { + "item": "rs:enchanted_gem", + "text": "Shilo Village master\\n(Level 100 combat required)", + "level": 50 + } + ] + } ] - } - \ No newline at end of file +} diff --git a/src/plugins/skills/skill-guides/smithing.json b/src/plugins/skills/skill-guides/smithing.json index 51ad9acf0..a2c43509a 100644 --- a/src/plugins/skills/skill-guides/smithing.json +++ b/src/plugins/skills/skill-guides/smithing.json @@ -1000,10 +1000,8 @@ "item": "rs:dragon_square_shield", "text": "Dragon square shield", "level": 60 - } - + } ] } - ] } diff --git a/src/plugins/skills/skill-guides/thieving.json b/src/plugins/skills/skill-guides/thieving.json index ba5822f56..e87ab93db 100644 --- a/src/plugins/skills/skill-guides/thieving.json +++ b/src/plugins/skills/skill-guides/thieving.json @@ -1,324 +1,327 @@ { - "id": 128, - "name": "Attack", - "members": true, - "sub_guides": [ - { - "name": "Pickpocket", - "lines": [ - { - "item": "rs:citizen", - "text": "Citizen", - "level": 1 - }, - { - "item": "rs:farmer", - "text": "Farmer", - "level": 10 - }, - { - "item": "rs:female_ham_follower", - "text": "Female H.A.M follower", - "level": 15 - }, - { - "item": "rs:male_ham_follower", - "text": "Male H.A.M follower", - "level": 20 - }, - { - "item": "rs:warrior", - "text": "Warrior", - "level": 25 - }, - { - "item": "rs:rogue", - "text": "Rogue", - "level": 32 - }, - { - "item": "rs:cave_goblin", - "text": "Cave goblin", - "level": 36 - }, - { - "item": "rs:master_farmer", - "text": "Master f armer", - "level": 38 - }, - { - "item": "rs:guard", - "text": "Guard", - "level": 40 - }, - { - "item": "rs:fremennik", - "text": "Fremennik", - "level": 45 - }, - { - "item": "rs:bearded_pollnivnian_bandit", - "text": "Bearded Pollnivnian bandit", - "level": 45 - }, - { - "item": "rs:desert_bandit", - "text": "Desert bandit", - "level": 53 - }, - { - "item": "rs:knight", - "text": "Knight", - "level": 55 - }, - { - "item": "rs:pollnivnian_bandit", - "text": "Pollnivnian bandit", - "level": 55 - }, - { - "item": "rs:watchman", - "text": "Watchman", - "level": 65 - }, - { - "item": "rs:menaphite_thug", - "text": "Menaphite thug", - "level": 65 - }, - { - "item": "rs:paladin", - "text": "Paladin", - "level": 70 - }, - { - "item": "rs:gnome", - "text": "Gnome", - "level": 75 - }, - { - "item": "rs:hero", - "text": "Hero", - "level": 80 - }, - { - "item": "rs:vyre", - "text": "Vyre", - "level": 82 - }, - { - "item": "rs:elf", - "text": "Elf", - "level": 85 - }, - { - "item": "rs:tzhaar", - "text": "TzHaar", - "level": 90 - } - ] - }, { - "name": "Stalls", - "lines": [ - { - "item": "rs:vegetable_stall", - "text": "Vegetable stall", - "level": 2 - }, - { - "item": "rs:Cake_stall", - "text": "Cake stall", - "level": 5 - }, - { - "item": "rs:tea_stall", - "text": "Tea stall", - "level": 5 - }, - { - "item": "rs:crafting_stall", - "text": "Crafting stall", - "level": 5 - }, - { - "item": "rs:monkey_food_stall", - "text": "Monkey food stall", - "level": 5 - }, - { - "item": "rs:silk_stall", - "text": "Silk stall", - "level": 20 - }, - { - "item": "rs:wine_stall", - "text": "Wine stall", - "level": 22 - }, - { - "item": "rs:fruit_stall", - "text": "Fruit stall", - "level": 25 - }, - { - "item": "rs:seed_stall", - "text": "Seed stall", - "level": 27 - }, - { - "item": "rs:fur_stall", - "text": "Fur stall", - "level": 35 - }, - { - "item": "rs:fish_stall", - "text": "Fish stall", - "level": 42 - }, - { - "item": "rs:crossbow_stall", - "text": "Crossbow stall", - "level": 49 - }, - { - "item": "rs:silver_stall", - "text": "Silver stall", - "level": 50 - }, - { - "item": "rs:magic_stall", - "text": "Magic stall", - "level": 65 - }, - { - "item": "rs:scimitar_stall", - "text": "Scimitar stall", - "level": 65 - }, - { - "item": "rs:spices_stall", - "text": "Spices stall", - "level": 65 - }, - { - "item": "rs:gems_stall", - "text": "Gems stall", - "level": 75 - }, - { - "item": "rs:ore_stall", - "text": "Ore stall", - "level": 82 - } - ] - }, { - "name": "Chests", - "lines": [ - { - "item": "rs:ardougne_relekka_wilderness", - "text": "Ardougne, Rellekka and the Wilderness", - "level": 13 - }, - { - "item": "rs:upstairs_ardougne_rellekka", - "text": "Upstairs in Ardougne and Rellekka", - "level": 28 - }, - { - "item": "rs:the_isles_of_souls", - "text": "The Isle of Souls", - "level": 28 - }, - { - "item": "rs:upstairs_ardougne", - "text": "Upstairs in Ardougne", - "level": 43 - }, - { - "item": "rs:hemenster_rellekka", - "text": "Hemenster and Rellekka", - "level": 47 - }, - { - "item": "rs:dorgesh_kaan_average_chest", - "text": "Dorgesh-Kaan (average chests)", - "level": 52 - }, - { - "item": "rs:chaos_druid_tower_north_ardougne", - "text": "Chaos druid tower north of Ardougne", - "level": 59 - }, - { - "item": "rs:lizardman_temple_molch", - "text": "Lizardman Temple beneath Molch", - "level": 64 - }, - { - "item": "rs:ardougne_castle", - "text": "Ardougne Castle", - "level": 72 - }, - { - "item": "rs:dorgesh_kaan_rich", - "text": "Dorgesh-Kaan (rich chests)", - "level": 78 - }, - { - "item": "rs:wilderness_rogues_castle", - "text": "Wilderness Rogue's Castle", - "level": 84 - } - ] - }, { - "name": "Other", - "lines": [ - { - "item": "rs:pyramid_plunder_room_1", - "text": "Pyramid Plunder minigame - Room 1\\nIn the Jalsavrah Pyramid in Sophanem", - "level": 21 - }, - { - "item": "rs:pyramid_plunder_room_2", - "text": "Pyramid Plunder - Room 2", - "level": 31 - }, - { - "item": "rs:pyramid_plunder_room_3", - "text": "Pyramid Plunder - Room 3", - "level": 41 - }, - { - "item": "rs:uncut_sapphire", - "text": "Can crack the wall safes in Rogues'Den", - "level": 50 - }, - { - "item": "rs:pyramid_plunder_room_4", - "text": "Pyramid Plunder - Room 4", - "level": 51 - }, - { - "item": "rs:pyramid_plunder_room_5", - "text": "Pyramid Plunder - Room 5", - "level": 61 - }, - { - "item": "rs:pyramid_plunder_room_6", - "text": "Pyramid Plunder - 6", - "level": 71 - }, - { - "item": "rs:pyramid_plunder_room_7", - "text": "Pyramid Plunder - 7)", - "level": 81 - }, - { - "item": "rs:pyramid_plunder_room_8", - "text": "Pyramid Plunder - 8", - "level": 91 + "id": 128, + "name": "Attack", + "members": true, + "sub_guides": [ + { + "name": "Pickpocket", + "lines": [ + { + "item": "rs:citizen", + "text": "Citizen", + "level": 1 + }, + { + "item": "rs:farmer", + "text": "Farmer", + "level": 10 + }, + { + "item": "rs:female_ham_follower", + "text": "Female H.A.M follower", + "level": 15 + }, + { + "item": "rs:male_ham_follower", + "text": "Male H.A.M follower", + "level": 20 + }, + { + "item": "rs:warrior", + "text": "Warrior", + "level": 25 + }, + { + "item": "rs:rogue", + "text": "Rogue", + "level": 32 + }, + { + "item": "rs:cave_goblin", + "text": "Cave goblin", + "level": 36 + }, + { + "item": "rs:master_farmer", + "text": "Master f armer", + "level": 38 + }, + { + "item": "rs:guard", + "text": "Guard", + "level": 40 + }, + { + "item": "rs:fremennik", + "text": "Fremennik", + "level": 45 + }, + { + "item": "rs:bearded_pollnivnian_bandit", + "text": "Bearded Pollnivnian bandit", + "level": 45 + }, + { + "item": "rs:desert_bandit", + "text": "Desert bandit", + "level": 53 + }, + { + "item": "rs:knight", + "text": "Knight", + "level": 55 + }, + { + "item": "rs:pollnivnian_bandit", + "text": "Pollnivnian bandit", + "level": 55 + }, + { + "item": "rs:watchman", + "text": "Watchman", + "level": 65 + }, + { + "item": "rs:menaphite_thug", + "text": "Menaphite thug", + "level": 65 + }, + { + "item": "rs:paladin", + "text": "Paladin", + "level": 70 + }, + { + "item": "rs:gnome", + "text": "Gnome", + "level": 75 + }, + { + "item": "rs:hero", + "text": "Hero", + "level": 80 + }, + { + "item": "rs:vyre", + "text": "Vyre", + "level": 82 + }, + { + "item": "rs:elf", + "text": "Elf", + "level": 85 + }, + { + "item": "rs:tzhaar", + "text": "TzHaar", + "level": 90 + } + ] + }, + { + "name": "Stalls", + "lines": [ + { + "item": "rs:vegetable_stall", + "text": "Vegetable stall", + "level": 2 + }, + { + "item": "rs:Cake_stall", + "text": "Cake stall", + "level": 5 + }, + { + "item": "rs:tea_stall", + "text": "Tea stall", + "level": 5 + }, + { + "item": "rs:crafting_stall", + "text": "Crafting stall", + "level": 5 + }, + { + "item": "rs:monkey_food_stall", + "text": "Monkey food stall", + "level": 5 + }, + { + "item": "rs:silk_stall", + "text": "Silk stall", + "level": 20 + }, + { + "item": "rs:wine_stall", + "text": "Wine stall", + "level": 22 + }, + { + "item": "rs:fruit_stall", + "text": "Fruit stall", + "level": 25 + }, + { + "item": "rs:seed_stall", + "text": "Seed stall", + "level": 27 + }, + { + "item": "rs:fur_stall", + "text": "Fur stall", + "level": 35 + }, + { + "item": "rs:fish_stall", + "text": "Fish stall", + "level": 42 + }, + { + "item": "rs:crossbow_stall", + "text": "Crossbow stall", + "level": 49 + }, + { + "item": "rs:silver_stall", + "text": "Silver stall", + "level": 50 + }, + { + "item": "rs:magic_stall", + "text": "Magic stall", + "level": 65 + }, + { + "item": "rs:scimitar_stall", + "text": "Scimitar stall", + "level": 65 + }, + { + "item": "rs:spices_stall", + "text": "Spices stall", + "level": 65 + }, + { + "item": "rs:gems_stall", + "text": "Gems stall", + "level": 75 + }, + { + "item": "rs:ore_stall", + "text": "Ore stall", + "level": 82 + } + ] + }, + { + "name": "Chests", + "lines": [ + { + "item": "rs:ardougne_relekka_wilderness", + "text": "Ardougne, Rellekka and the Wilderness", + "level": 13 + }, + { + "item": "rs:upstairs_ardougne_rellekka", + "text": "Upstairs in Ardougne and Rellekka", + "level": 28 + }, + { + "item": "rs:the_isles_of_souls", + "text": "The Isle of Souls", + "level": 28 + }, + { + "item": "rs:upstairs_ardougne", + "text": "Upstairs in Ardougne", + "level": 43 + }, + { + "item": "rs:hemenster_rellekka", + "text": "Hemenster and Rellekka", + "level": 47 + }, + { + "item": "rs:dorgesh_kaan_average_chest", + "text": "Dorgesh-Kaan (average chests)", + "level": 52 + }, + { + "item": "rs:chaos_druid_tower_north_ardougne", + "text": "Chaos druid tower north of Ardougne", + "level": 59 + }, + { + "item": "rs:lizardman_temple_molch", + "text": "Lizardman Temple beneath Molch", + "level": 64 + }, + { + "item": "rs:ardougne_castle", + "text": "Ardougne Castle", + "level": 72 + }, + { + "item": "rs:dorgesh_kaan_rich", + "text": "Dorgesh-Kaan (rich chests)", + "level": 78 + }, + { + "item": "rs:wilderness_rogues_castle", + "text": "Wilderness Rogue's Castle", + "level": 84 + } + ] + }, + { + "name": "Other", + "lines": [ + { + "item": "rs:pyramid_plunder_room_1", + "text": "Pyramid Plunder minigame - Room 1\\nIn the Jalsavrah Pyramid in Sophanem", + "level": 21 + }, + { + "item": "rs:pyramid_plunder_room_2", + "text": "Pyramid Plunder - Room 2", + "level": 31 + }, + { + "item": "rs:pyramid_plunder_room_3", + "text": "Pyramid Plunder - Room 3", + "level": 41 + }, + { + "item": "rs:uncut_sapphire", + "text": "Can crack the wall safes in Rogues'Den", + "level": 50 + }, + { + "item": "rs:pyramid_plunder_room_4", + "text": "Pyramid Plunder - Room 4", + "level": 51 + }, + { + "item": "rs:pyramid_plunder_room_5", + "text": "Pyramid Plunder - Room 5", + "level": 61 + }, + { + "item": "rs:pyramid_plunder_room_6", + "text": "Pyramid Plunder - 6", + "level": 71 + }, + { + "item": "rs:pyramid_plunder_room_7", + "text": "Pyramid Plunder - 7)", + "level": 81 + }, + { + "item": "rs:pyramid_plunder_room_8", + "text": "Pyramid Plunder - 8", + "level": 91 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/skill-guides/woodcutting.json b/src/plugins/skills/skill-guides/woodcutting.json index 34e5b7879..3984f2f31 100644 --- a/src/plugins/skills/skill-guides/woodcutting.json +++ b/src/plugins/skills/skill-guides/woodcutting.json @@ -1,112 +1,112 @@ { - "id": 139, - "name": "Woodcutting", - "members": false, - "sub_guides": [ - { - "name": "Trees", - "lines": [ - { - "item": "rs:logs", - "text": "Normal trees", - "level": 1 - }, - { - "item": "rs:achey_logs", - "text": "Achey trees", - "level": 1 - }, - { - "item": "rs:oak_logs", - "text": "Oak trees", - "level": 15 - }, - { - "item": "rs:willow_logs", - "text": "Willow trees", - "level": 30 - }, - { - "item": "rs:teak_logs", - "text": "Teak trees", - "level": 35 - }, - { - "item": "rs:maple_logs", - "text": "Maple trees", - "level": 45 - }, - { - "item": "rs:mahogany_logs", - "text": "Mahogany trees", - "level": 50 + "id": 139, + "name": "Woodcutting", + "members": false, + "sub_guides": [ + { + "name": "Trees", + "lines": [ + { + "item": "rs:logs", + "text": "Normal trees", + "level": 1 + }, + { + "item": "rs:achey_logs", + "text": "Achey trees", + "level": 1 + }, + { + "item": "rs:oak_logs", + "text": "Oak trees", + "level": 15 + }, + { + "item": "rs:willow_logs", + "text": "Willow trees", + "level": 30 + }, + { + "item": "rs:teak_logs", + "text": "Teak trees", + "level": 35 + }, + { + "item": "rs:maple_logs", + "text": "Maple trees", + "level": 45 + }, + { + "item": "rs:mahogany_logs", + "text": "Mahogany trees", + "level": 50 + }, + { + "item": "rs:yew_logs", + "text": "Yew trees", + "level": 60 + }, + { + "item": "rs:magic_logs", + "text": "Magic trees", + "level": 75 + } + ] }, { - "item": "rs:yew_logs", - "text": "Yew trees", - "level": 60 + "name": "Axes", + "lines": [ + { + "item": "rs:bronze_axe", + "text": "Bronze axe", + "level": 1 + }, + { + "item": "rs:iron_axe", + "text": "Iron axe", + "level": 1 + }, + { + "item": "rs:steel_axe", + "text": "Steel axe", + "level": 6 + }, + { + "item": "rs:black_axe", + "text": "Black axe", + "level": 11 + }, + { + "item": "rs:mithril_axe", + "text": "Mithril axe", + "level": 21 + }, + { + "item": "rs:adamant_axe", + "text": "Adamant axe", + "level": 31 + }, + { + "item": "rs:rune_axe", + "text": "Rune axe", + "level": 41 + }, + { + "item": "rs:dragon_axe", + "text": "Dragon axe", + "level": 61 + } + ] }, { - "item": "rs:magic_logs", - "text": "Magic trees", - "level": 75 - } - ] - }, - { - "name": "Axes", - "lines": [ - { - "item": "rs:bronze_axe", - "text": "Bronze axe", - "level": 1 - }, - { - "item": "rs:iron_axe", - "text": "Iron axe", - "level": 1 - }, - { - "item": "rs:steel_axe", - "text": "Steel axe", - "level": 6 - }, - { - "item": "rs:black_axe", - "text": "Black axe", - "level": 11 - }, - { - "item": "rs:mithril_axe", - "text": "Mithril axe", - "level": 21 - }, - { - "item": "rs:adamant_axe", - "text": "Adamant axe", - "level": 31 - }, - { - "item": "rs:rune_axe", - "text": "Rune axe", - "level": 41 - }, - { - "item": "rs:dragon_axe", - "text": "Dragon axe", - "level": 61 - } - ] - }, - { - "name": "Other", - "lines": [ - { - "item": "rs:dwarf_remains", - "text": "Missing content", - "level": 1 + "name": "Other", + "lines": [ + { + "item": "rs:dwarf_remains", + "text": "Missing content", + "level": 1 + } + ] } - ] - } - ] + ] } diff --git a/src/plugins/skills/smithing/forging-constants.ts b/src/plugins/skills/smithing/forging-constants.ts index 16bbbe963..a97c4dbee 100644 --- a/src/plugins/skills/smithing/forging-constants.ts +++ b/src/plugins/skills/smithing/forging-constants.ts @@ -1,1903 +1,2588 @@ import { itemIds } from '@engine/world/config/item-ids'; import type { Smithable } from '@plugins/skills/smithing/forging-types'; -export const anvilIds: number[] = [ - 2782, 2783, 4306, 6150 -]; +export const anvilIds: number[] = [2782, 2783, 4306, 6150]; /** * Map bars and levels. */ -export const bars : Map = new Map([ +export const bars: Map = new Map([ [itemIds.bars.bronze, 1], [itemIds.bars.iron, 15], [itemIds.bars.steel, 30], [itemIds.bars.mithril, 50], [itemIds.bars.adamantite, 70], - [itemIds.bars.runite, 85] + [itemIds.bars.runite, 85], ]); -export const smithables : Map> = new Map>([ - ['dagger', new Map([ - ['bronze', { - level: 1, - experience: 12.5, - item: { itemId: itemIds.daggers.bronze, amount: 1 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 15, - experience: 25, - item: { itemId: itemIds.daggers.iron, amount: 1 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 30, - experience: 37.5, - item: { itemId: itemIds.daggers.steel, amount: 1 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 50, - experience: 50, - item: { itemId: itemIds.daggers.mithril, amount: 1 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 70, - experience: 62.5, - item: { itemId: itemIds.daggers.adamant, amount: 1 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 85, - experience: 75, - item: { itemId: itemIds.daggers.rune, amount: 1 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }], - ])], - ['axe', new Map([ - ['bronze', { - level: 1, - experience: 12.5, - item: { itemId: itemIds.axes.bronze, amount: 1 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 16, - experience: 25, - item: { itemId: itemIds.axes.iron, amount: 1 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 31, - experience: 37.5, - item: { itemId: itemIds.axes.steel, amount: 1 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 51, - experience: 50, - item: { itemId: itemIds.axes.mithril, amount: 1 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 71, - experience: 62.5, - item: { itemId: itemIds.axes.adamantite, amount: 1 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 86, - experience: 75, - item: { itemId: itemIds.axes.runite, amount: 1 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }], - ])], - ['mace', new Map([ - ['bronze', { - level: 2, - experience: 12.5, - item: { itemId: itemIds.maces.bronze, amount: 1 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 17, - experience: 25, - item: { itemId: itemIds.maces.iron, amount: 1 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 32, - experience: 37.5, - item: { itemId: itemIds.maces.steel, amount: 1 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 52, - experience: 50, - item: { itemId: itemIds.maces.mithril, amount: 1 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 72, - experience: 62.5, - item: { itemId: itemIds.maces.adamantite, amount: 1 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 87, - experience: 75, - item: { itemId: itemIds.maces.runite, amount: 1 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }], - ])], - ['mediumHelm', new Map([ - ['bronze', { - level: 3, - experience: 12.5, - item: { itemId: itemIds.mediumHelmets.bronze, amount: 1 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 18, - experience: 25, - item: { itemId: itemIds.mediumHelmets.iron, amount: 1 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 33, - experience: 37.5, - item: { itemId: itemIds.mediumHelmets.steel, amount: 1 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 53, - experience: 50, - item: { itemId: itemIds.mediumHelmets.mithril, amount: 1 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 73, - experience: 62.5, - item: { itemId: itemIds.mediumHelmets.adamantite, amount: 1 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 88, - experience: 75, - item: { itemId: itemIds.mediumHelmets.runite, amount: 1 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }] - ])], - ['bolts', new Map([ - ['bronze', { - level: 3, - experience: 12.5, - item: { itemId: itemIds.bolts.bronze, amount: 15 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 18, - experience: 25, - item: { itemId: itemIds.bolts.iron, amount: 15 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 33, - experience: 37.5, - item: { itemId: itemIds.bolts.steel, amount: 15 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 53, - experience: 50, - item: { itemId: itemIds.bolts.mithril, amount: 15 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 73, - experience: 62.5, - item: { itemId: itemIds.bolts.adamantite, amount: 15 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 88, - experience: 75, - item: { itemId: itemIds.bolts.runite, amount: 15 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }], - ])], - ['sword', new Map([ - ['bronze', { - level: 4, - experience: 12.5, - item: { itemId: itemIds.swords.bronze, amount: 1 }, - ingredient: { itemId: itemIds.bars.bronze, amount: 1 } - }], - ['iron', { - level: 19, - experience: 25, - item: { itemId: itemIds.swords.iron, amount: 1 }, - ingredient: { itemId: itemIds.bars.iron, amount: 1 } - }], - ['steel', { - level: 34, - experience: 37.5, - item: { itemId: itemIds.swords.steel, amount: 1 }, - ingredient: { itemId: itemIds.bars.steel, amount: 1 } - }], - ['mithril', { - level: 54, - experience: 50, - item: { itemId: itemIds.swords.mithril, amount: 1 }, - ingredient: { itemId: itemIds.bars.mithril, amount: 1 } - }], - ['adamant', { - level: 74, - experience: 62.5, - item: { itemId: itemIds.swords.adamantite, amount: 1 }, - ingredient: { itemId: itemIds.bars.adamantite, amount: 1 } - }], - ['rune', { - level: 89, - experience: 75, - item: { itemId: itemIds.swords.runite, amount: 1 }, - ingredient: { itemId: itemIds.bars.runite, amount: 1 } - }], - ])], - ['dartTips', new Map([ - ['bronze', { - level: 4, - experience: 12.5, - item: { - itemId: itemIds.dartTips.bronze, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }], - ['iron', { - level: 19, - experience: 25, - item: { - itemId: itemIds.dartTips.iron, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 1 - } - }], - ['steel', { - level: 34, - experience: 37.5, - item: { - itemId: itemIds.dartTips.steel, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 54, - experience: 50, - item: { - itemId: itemIds.dartTips.mithril, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 74, - experience: 62.5, - item: { - itemId: itemIds.dartTips.adamantite, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 89, - experience: 75, - item: { - itemId: itemIds.dartTips.runite, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['nails', new Map([ - ['bronze', { - level: 4, - experience: 12.5, - item: { - itemId: itemIds.nails.bronze, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }], - ['iron', { - level: 19, - experience: 25, - item: { - itemId: itemIds.nails.iron, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 1 - } - }], - ['steel', { - level: 34, - experience: 37.5, - item: { - itemId: itemIds.nails.steel, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 54, - experience: 50, - item: { - itemId: itemIds.nails.mithril, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 74, - experience: 62.5, - item: { - itemId: itemIds.nails.adamantite, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 89, - experience: 75, - item: { - itemId: itemIds.nails.runite, - amount: 10 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['scimitar', new Map([ - ['bronze', { - level: 5, - experience: 25, - item: { - itemId: itemIds.scimitars.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 2 - } - }], - ['iron', { - level: 20, - experience: 50, - item: { - itemId: itemIds.scimitars.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 2 - } - }], - ['steel', { - level: 35, - experience: 75, - item: { - itemId: itemIds.scimitars.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 2 - } - }], - ['mithril', { - level: 55, - experience: 100, - item: { - itemId: itemIds.scimitars.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 2 - } - }], - ['adamant', { - level: 75, - experience: 125, - item: { - itemId: itemIds.scimitars.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 2 - } - }], - ['rune', { - level: 90, - experience: 150, - item: { - itemId: itemIds.scimitars.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 2 - } - }], - ])], - ['spear', new Map([ - ['bronze', { - level: 5, - experience: 25, - item: { - itemId: itemIds.spears.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }], - ['iron', { - level: 20, - experience: 25, - item: { - itemId: itemIds.spears.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 1 - } - }], - ['steel', { - level: 35, - experience: 37.5, - item: { - itemId: itemIds.spears.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 55, - experience: 50, - item: { - itemId: itemIds.spears.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 75, - experience: 62.5, - item: { - itemId: itemIds.spears.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 90, - experience: 75, - item: { - itemId: itemIds.spears.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['arrowTips', new Map([ - ['bronze', { - level: 5, - experience: 12.5, - item: { - itemId: itemIds.arrowTips.bronze, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }], - ['iron', { - level: 20, - experience: 25, - item: { - itemId: itemIds.arrowTips.iron, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 1 - } - }], - ['steel', { - level: 35, - experience: 37.5, - item: { - itemId: itemIds.arrowTips.steel, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 55, - experience: 50, - item: { - itemId: itemIds.arrowTips.mithril, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 75, - experience: 62.5, - item: { - itemId: itemIds.arrowTips.adamantite, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 90, - experience: 75, - item: { - itemId: itemIds.arrowTips.runite, - amount: 15 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['limbs', new Map < string, Smithable > ([ - ['bronze', { - level: 6, - experience: 12.5, - item: { - itemId: itemIds.limbs.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }], - ['iron', { - level: 23, - experience: 25, - item: { - itemId: itemIds.limbs.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 1 - } - }], - ['steel', { - level: 36, - experience: 37.5, - item: { - itemId: itemIds.limbs.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 56, - experience: 50, - item: { - itemId: itemIds.limbs.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 76, - experience: 62.5, - item: { - itemId: itemIds.limbs.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 91, - experience: 75, - item: { - itemId: itemIds.limbs.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['longsword', new Map < string, Smithable > ([ - ['bronze', { - level: 6, - experience: 25, - item: { - itemId: itemIds.longswords.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 2 - } - }], - ['iron', { - level: 21, - experience: 50, - item: { - itemId: itemIds.longswords.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 2 - } - }], - ['steel', { - level: 36, - experience: 75, - item: { - itemId: itemIds.longswords.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 2 - } - }], - ['mithril', { - level: 56, - experience: 100, - item: { - itemId: itemIds.longswords.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 2 - } - }], - ['adamant', { - level: 76, - experience: 125, - item: { - itemId: itemIds.longswords.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 2 - } - }], - ['rune', { - level: 91, - experience: 150, - item: { - itemId: itemIds.longswords.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 2 - } - }], - ])], - ['fullHelm', new Map < string, Smithable > ([ - ['bronze', { - level: 7, - experience: 25, - item: { - itemId: itemIds.fullHelmets.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 2 - } - }], - ['iron', { - level: 22, - experience: 50, - item: { - itemId: itemIds.fullHelmets.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 2 - } - }], - ['steel', { - level: 37, - experience: 75, - item: { - itemId: itemIds.fullHelmets.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 2 - } - }], - ['mithril', { - level: 57, - experience: 100, - item: { - itemId: itemIds.fullHelmets.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 2 - } - }], - ['adamant', { - level: 77, - experience: 125, - item: { - itemId: itemIds.fullHelmets.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 2 - } - }], - ['rune', { - level: 92, - experience: 150, - item: { - itemId: itemIds.fullHelmets.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 2 - } - }], - ])], - ['knife', new Map < string, Smithable > ([ - ['steel', { - level: 37, - experience: 37.5, - item: { - itemId: itemIds.throwingKnives.steel, - amount: 5 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 1 - } - }], - ['mithril', { - level: 57, - experience: 50, - item: { - itemId: itemIds.throwingKnives.mithril, - amount: 5 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 1 - } - }], - ['adamant', { - level: 77, - experience: 62.5, - item: { - itemId: itemIds.throwingKnives.adamantite, - amount: 5 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 1 - } - }], - ['rune', { - level: 92, - experience: 75, - item: { - itemId: itemIds.throwingKnives.runite, - amount: 5 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 1 - } - }], - ])], - ['squareShield', new Map < string, Smithable > ([ - ['bronze', { - level: 8, - experience: 25, - item: { - itemId: itemIds.squareShields.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 2 - } - }], - ['iron', { - level: 23, - experience: 50, - item: { - itemId: itemIds.squareShields.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 2 - } - }], - ['steel', { - level: 38, - experience: 75, - item: { - itemId: itemIds.squareShields.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 2 - } - }], - ['mithril', { - level: 58, - experience: 100, - item: { - itemId: itemIds.squareShields.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 2 - } - }], - ['adamant', { - level: 78, - experience: 125, - item: { - itemId: itemIds.squareShields.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 2 - } - }], - ['rune', { - level: 93, - experience: 150, - item: { - itemId: itemIds.squareShields.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 2 - } - }], - ])], - ['warhammer', new Map < string, Smithable > ([ - ['bronze', { - level: 9, - experience: 37.5, - item: { - itemId: itemIds.warhammers.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 24, - experience: 75, - item: { - itemId: itemIds.warhammers.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 39, - experience: 112.5, - item: { - itemId: itemIds.warhammers.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 59, - experience: 150, - item: { - itemId: itemIds.warhammers.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 79, - experience: 187.5, - item: { - itemId: itemIds.warhammers.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 94, - experience: 225, - item: { - itemId: itemIds.warhammers.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['battleaxe', new Map < string, Smithable > ([ - ['bronze', { - level: 9, - experience: 37.5, - item: { - itemId: itemIds.battleAxes.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 24, - experience: 75, - item: { - itemId: itemIds.battleAxes.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 39, - experience: 112.5, - item: { - itemId: itemIds.battleAxes.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 59, - experience: 150, - item: { - itemId: itemIds.battleAxes.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 79, - experience: 187.5, - item: { - itemId: itemIds.battleAxes.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 94, - experience: 225, - item: { - itemId: itemIds.battleAxes.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['chainbody', new Map < string, Smithable > ([ - ['bronze', { - level: 11, - experience: 37.5, - item: { - itemId: itemIds.chainbodies.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 26, - experience: 75, - item: { - itemId: itemIds.chainbodies.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 41, - experience: 112.5, - item: { - itemId: itemIds.chainbodies.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 61, - experience: 150, - item: { - itemId: itemIds.chainbodies.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 81, - experience: 187.5, - item: { - itemId: itemIds.chainbodies.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 96, - experience: 225, - item: { - itemId: itemIds.chainbodies.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['kiteshield', new Map([ - ['bronze', { - level: 12, - experience: 37.5, - item: { - itemId: itemIds.kiteshields.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 27, - experience: 75, - item: { - itemId: itemIds.kiteshields.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 42, - experience: 112.5, - item: { - itemId: itemIds.kiteshields.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 62, - experience: 150, - item: { - itemId: itemIds.kiteshields.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 82, - experience: 187.5, - item: { - itemId: itemIds.kiteshields.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 97, - experience: 225, - item: { - itemId: itemIds.kiteshields.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['claws', new Map < string, Smithable > ([ - ['bronze', { - level: 13, - experience: 25, - item: { - itemId: itemIds.claws.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 2 - } - }], - ['iron', { - level: 28, - experience: 50, - item: { - itemId: itemIds.claws.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 2 - } - }], - ['steel', { - level: 43, - experience: 75, - item: { - itemId: itemIds.claws.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 2 - } - }], - ['mithril', { - level: 63, - experience: 100, - item: { - itemId: itemIds.claws.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 2 - } - }], - ['adamant', { - level: 83, - experience: 125, - item: { - itemId: itemIds.claws.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 2 - } - }], - ['rune', { - level: 98, - experience: 150, - item: { - itemId: itemIds.claws.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 2 - } - }], - ])], - ['twoHandedSword', new Map < string, Smithable > ([ - ['bronze', { - level: 14, - experience: 37.5, - item: { - itemId: itemIds.twoHandSwords.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 29, - experience: 75, - item: { - itemId: itemIds.twoHandSwords.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 44, - experience: 112.5, - item: { - itemId: itemIds.twoHandSwords.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 64, - experience: 150, - item: { - itemId: itemIds.twoHandSwords.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 84, - experience: 187.5, - item: { - itemId: itemIds.twoHandSwords.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 99, - experience: 225, - item: { - itemId: itemIds.twoHandSwords.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['platelegs', new Map([ - ['bronze', { - level: 16, - experience: 37.5, - item: { - itemId: itemIds.platelegs.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 31, - experience: 75, - item: { - itemId: itemIds.platelegs.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 46, - experience: 112.5, - item: { - itemId: itemIds.platelegs.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 66, - experience: 150, - item: { - itemId: itemIds.platelegs.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 86, - experience: 187.5, - item: { - itemId: itemIds.platelegs.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 99, - experience: 225, - item: { - itemId: itemIds.platelegs.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['plateskirt', new Map < string, Smithable > ([ - ['bronze', { - level: 16, - experience: 37.5, - item: { - itemId: itemIds.plateskirts.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 3 - } - }], - ['iron', { - level: 31, - experience: 75, - item: { - itemId: itemIds.plateskirts.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 3 - } - }], - ['steel', { - level: 46, - experience: 112.5, - item: { - itemId: itemIds.plateskirts.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 3 - } - }], - ['mithril', { - level: 66, - experience: 150, - item: { - itemId: itemIds.plateskirts.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 3 - } - }], - ['adamant', { - level: 86, - experience: 187.5, - item: { - itemId: itemIds.plateskirts.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 3 - } - }], - ['rune', { - level: 99, - experience: 225, - item: { - itemId: itemIds.plateskirts.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 3 - } - }], - ])], - ['platebody', new Map([ - ['bronze', { - level: 16, - experience: 37.5, - item: { - itemId: itemIds.platebodys.bronze, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 5 - } - }], - ['iron', { - level: 31, - experience: 75, - item: { - itemId: itemIds.platebodys.iron, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.iron, - amount: 5 - } - }], - ['steel', { - level: 46, - experience: 112.5, - item: { - itemId: itemIds.platebodys.steel, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.steel, - amount: 5 - } - }], - ['mithril', { - level: 66, - experience: 150, - item: { - itemId: itemIds.platebodys.mithril, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.mithril, - amount: 5 - } - }], - ['adamant', { - level: 86, - experience: 187.5, - item: { - itemId: itemIds.platebodys.adamantite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.adamantite, - amount: 5 - } - }], - ['rune', { - level: 99, - experience: 225, - item: { - itemId: itemIds.platebodys.runite, - amount: 1 - }, - ingredient: { - itemId: itemIds.bars.runite, - amount: 5 - } - }], - ])], - ['unknown', new Map < string, Smithable > ([ - ['any', { - level: 1, - experience: 0, - item: { - itemId: -1, - amount: -1 - }, - ingredient: { - itemId: itemIds.bars.bronze, - amount: 1 - } - }] - ])], +export const smithables: Map> = new Map>([ + [ + 'dagger', + new Map([ + [ + 'bronze', + { + level: 1, + experience: 12.5, + item: { itemId: itemIds.daggers.bronze, amount: 1 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 15, + experience: 25, + item: { itemId: itemIds.daggers.iron, amount: 1 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 30, + experience: 37.5, + item: { itemId: itemIds.daggers.steel, amount: 1 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 50, + experience: 50, + item: { itemId: itemIds.daggers.mithril, amount: 1 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 70, + experience: 62.5, + item: { itemId: itemIds.daggers.adamant, amount: 1 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 85, + experience: 75, + item: { itemId: itemIds.daggers.rune, amount: 1 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'axe', + new Map([ + [ + 'bronze', + { + level: 1, + experience: 12.5, + item: { itemId: itemIds.axes.bronze, amount: 1 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 16, + experience: 25, + item: { itemId: itemIds.axes.iron, amount: 1 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 31, + experience: 37.5, + item: { itemId: itemIds.axes.steel, amount: 1 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 51, + experience: 50, + item: { itemId: itemIds.axes.mithril, amount: 1 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 71, + experience: 62.5, + item: { itemId: itemIds.axes.adamantite, amount: 1 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 86, + experience: 75, + item: { itemId: itemIds.axes.runite, amount: 1 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'mace', + new Map([ + [ + 'bronze', + { + level: 2, + experience: 12.5, + item: { itemId: itemIds.maces.bronze, amount: 1 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 17, + experience: 25, + item: { itemId: itemIds.maces.iron, amount: 1 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 32, + experience: 37.5, + item: { itemId: itemIds.maces.steel, amount: 1 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 52, + experience: 50, + item: { itemId: itemIds.maces.mithril, amount: 1 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 72, + experience: 62.5, + item: { itemId: itemIds.maces.adamantite, amount: 1 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 87, + experience: 75, + item: { itemId: itemIds.maces.runite, amount: 1 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'mediumHelm', + new Map([ + [ + 'bronze', + { + level: 3, + experience: 12.5, + item: { itemId: itemIds.mediumHelmets.bronze, amount: 1 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 18, + experience: 25, + item: { itemId: itemIds.mediumHelmets.iron, amount: 1 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 33, + experience: 37.5, + item: { itemId: itemIds.mediumHelmets.steel, amount: 1 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 53, + experience: 50, + item: { itemId: itemIds.mediumHelmets.mithril, amount: 1 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 73, + experience: 62.5, + item: { itemId: itemIds.mediumHelmets.adamantite, amount: 1 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 88, + experience: 75, + item: { itemId: itemIds.mediumHelmets.runite, amount: 1 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'bolts', + new Map([ + [ + 'bronze', + { + level: 3, + experience: 12.5, + item: { itemId: itemIds.bolts.bronze, amount: 15 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 18, + experience: 25, + item: { itemId: itemIds.bolts.iron, amount: 15 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 33, + experience: 37.5, + item: { itemId: itemIds.bolts.steel, amount: 15 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 53, + experience: 50, + item: { itemId: itemIds.bolts.mithril, amount: 15 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 73, + experience: 62.5, + item: { itemId: itemIds.bolts.adamantite, amount: 15 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 88, + experience: 75, + item: { itemId: itemIds.bolts.runite, amount: 15 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'sword', + new Map([ + [ + 'bronze', + { + level: 4, + experience: 12.5, + item: { itemId: itemIds.swords.bronze, amount: 1 }, + ingredient: { itemId: itemIds.bars.bronze, amount: 1 }, + }, + ], + [ + 'iron', + { + level: 19, + experience: 25, + item: { itemId: itemIds.swords.iron, amount: 1 }, + ingredient: { itemId: itemIds.bars.iron, amount: 1 }, + }, + ], + [ + 'steel', + { + level: 34, + experience: 37.5, + item: { itemId: itemIds.swords.steel, amount: 1 }, + ingredient: { itemId: itemIds.bars.steel, amount: 1 }, + }, + ], + [ + 'mithril', + { + level: 54, + experience: 50, + item: { itemId: itemIds.swords.mithril, amount: 1 }, + ingredient: { itemId: itemIds.bars.mithril, amount: 1 }, + }, + ], + [ + 'adamant', + { + level: 74, + experience: 62.5, + item: { itemId: itemIds.swords.adamantite, amount: 1 }, + ingredient: { itemId: itemIds.bars.adamantite, amount: 1 }, + }, + ], + [ + 'rune', + { + level: 89, + experience: 75, + item: { itemId: itemIds.swords.runite, amount: 1 }, + ingredient: { itemId: itemIds.bars.runite, amount: 1 }, + }, + ], + ]), + ], + [ + 'dartTips', + new Map([ + [ + 'bronze', + { + level: 4, + experience: 12.5, + item: { + itemId: itemIds.dartTips.bronze, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + [ + 'iron', + { + level: 19, + experience: 25, + item: { + itemId: itemIds.dartTips.iron, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 1, + }, + }, + ], + [ + 'steel', + { + level: 34, + experience: 37.5, + item: { + itemId: itemIds.dartTips.steel, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 54, + experience: 50, + item: { + itemId: itemIds.dartTips.mithril, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 74, + experience: 62.5, + item: { + itemId: itemIds.dartTips.adamantite, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 89, + experience: 75, + item: { + itemId: itemIds.dartTips.runite, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'nails', + new Map([ + [ + 'bronze', + { + level: 4, + experience: 12.5, + item: { + itemId: itemIds.nails.bronze, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + [ + 'iron', + { + level: 19, + experience: 25, + item: { + itemId: itemIds.nails.iron, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 1, + }, + }, + ], + [ + 'steel', + { + level: 34, + experience: 37.5, + item: { + itemId: itemIds.nails.steel, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 54, + experience: 50, + item: { + itemId: itemIds.nails.mithril, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 74, + experience: 62.5, + item: { + itemId: itemIds.nails.adamantite, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 89, + experience: 75, + item: { + itemId: itemIds.nails.runite, + amount: 10, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'scimitar', + new Map([ + [ + 'bronze', + { + level: 5, + experience: 25, + item: { + itemId: itemIds.scimitars.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 2, + }, + }, + ], + [ + 'iron', + { + level: 20, + experience: 50, + item: { + itemId: itemIds.scimitars.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 2, + }, + }, + ], + [ + 'steel', + { + level: 35, + experience: 75, + item: { + itemId: itemIds.scimitars.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 2, + }, + }, + ], + [ + 'mithril', + { + level: 55, + experience: 100, + item: { + itemId: itemIds.scimitars.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 2, + }, + }, + ], + [ + 'adamant', + { + level: 75, + experience: 125, + item: { + itemId: itemIds.scimitars.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 2, + }, + }, + ], + [ + 'rune', + { + level: 90, + experience: 150, + item: { + itemId: itemIds.scimitars.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 2, + }, + }, + ], + ]), + ], + [ + 'spear', + new Map([ + [ + 'bronze', + { + level: 5, + experience: 25, + item: { + itemId: itemIds.spears.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + [ + 'iron', + { + level: 20, + experience: 25, + item: { + itemId: itemIds.spears.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 1, + }, + }, + ], + [ + 'steel', + { + level: 35, + experience: 37.5, + item: { + itemId: itemIds.spears.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 55, + experience: 50, + item: { + itemId: itemIds.spears.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 75, + experience: 62.5, + item: { + itemId: itemIds.spears.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 90, + experience: 75, + item: { + itemId: itemIds.spears.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'arrowTips', + new Map([ + [ + 'bronze', + { + level: 5, + experience: 12.5, + item: { + itemId: itemIds.arrowTips.bronze, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + [ + 'iron', + { + level: 20, + experience: 25, + item: { + itemId: itemIds.arrowTips.iron, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 1, + }, + }, + ], + [ + 'steel', + { + level: 35, + experience: 37.5, + item: { + itemId: itemIds.arrowTips.steel, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 55, + experience: 50, + item: { + itemId: itemIds.arrowTips.mithril, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 75, + experience: 62.5, + item: { + itemId: itemIds.arrowTips.adamantite, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 90, + experience: 75, + item: { + itemId: itemIds.arrowTips.runite, + amount: 15, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'limbs', + new Map([ + [ + 'bronze', + { + level: 6, + experience: 12.5, + item: { + itemId: itemIds.limbs.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + [ + 'iron', + { + level: 23, + experience: 25, + item: { + itemId: itemIds.limbs.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 1, + }, + }, + ], + [ + 'steel', + { + level: 36, + experience: 37.5, + item: { + itemId: itemIds.limbs.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 56, + experience: 50, + item: { + itemId: itemIds.limbs.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 76, + experience: 62.5, + item: { + itemId: itemIds.limbs.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 91, + experience: 75, + item: { + itemId: itemIds.limbs.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'longsword', + new Map([ + [ + 'bronze', + { + level: 6, + experience: 25, + item: { + itemId: itemIds.longswords.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 2, + }, + }, + ], + [ + 'iron', + { + level: 21, + experience: 50, + item: { + itemId: itemIds.longswords.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 2, + }, + }, + ], + [ + 'steel', + { + level: 36, + experience: 75, + item: { + itemId: itemIds.longswords.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 2, + }, + }, + ], + [ + 'mithril', + { + level: 56, + experience: 100, + item: { + itemId: itemIds.longswords.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 2, + }, + }, + ], + [ + 'adamant', + { + level: 76, + experience: 125, + item: { + itemId: itemIds.longswords.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 2, + }, + }, + ], + [ + 'rune', + { + level: 91, + experience: 150, + item: { + itemId: itemIds.longswords.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 2, + }, + }, + ], + ]), + ], + [ + 'fullHelm', + new Map([ + [ + 'bronze', + { + level: 7, + experience: 25, + item: { + itemId: itemIds.fullHelmets.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 2, + }, + }, + ], + [ + 'iron', + { + level: 22, + experience: 50, + item: { + itemId: itemIds.fullHelmets.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 2, + }, + }, + ], + [ + 'steel', + { + level: 37, + experience: 75, + item: { + itemId: itemIds.fullHelmets.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 2, + }, + }, + ], + [ + 'mithril', + { + level: 57, + experience: 100, + item: { + itemId: itemIds.fullHelmets.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 2, + }, + }, + ], + [ + 'adamant', + { + level: 77, + experience: 125, + item: { + itemId: itemIds.fullHelmets.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 2, + }, + }, + ], + [ + 'rune', + { + level: 92, + experience: 150, + item: { + itemId: itemIds.fullHelmets.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 2, + }, + }, + ], + ]), + ], + [ + 'knife', + new Map([ + [ + 'steel', + { + level: 37, + experience: 37.5, + item: { + itemId: itemIds.throwingKnives.steel, + amount: 5, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 1, + }, + }, + ], + [ + 'mithril', + { + level: 57, + experience: 50, + item: { + itemId: itemIds.throwingKnives.mithril, + amount: 5, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 1, + }, + }, + ], + [ + 'adamant', + { + level: 77, + experience: 62.5, + item: { + itemId: itemIds.throwingKnives.adamantite, + amount: 5, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 1, + }, + }, + ], + [ + 'rune', + { + level: 92, + experience: 75, + item: { + itemId: itemIds.throwingKnives.runite, + amount: 5, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 1, + }, + }, + ], + ]), + ], + [ + 'squareShield', + new Map([ + [ + 'bronze', + { + level: 8, + experience: 25, + item: { + itemId: itemIds.squareShields.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 2, + }, + }, + ], + [ + 'iron', + { + level: 23, + experience: 50, + item: { + itemId: itemIds.squareShields.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 2, + }, + }, + ], + [ + 'steel', + { + level: 38, + experience: 75, + item: { + itemId: itemIds.squareShields.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 2, + }, + }, + ], + [ + 'mithril', + { + level: 58, + experience: 100, + item: { + itemId: itemIds.squareShields.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 2, + }, + }, + ], + [ + 'adamant', + { + level: 78, + experience: 125, + item: { + itemId: itemIds.squareShields.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 2, + }, + }, + ], + [ + 'rune', + { + level: 93, + experience: 150, + item: { + itemId: itemIds.squareShields.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 2, + }, + }, + ], + ]), + ], + [ + 'warhammer', + new Map([ + [ + 'bronze', + { + level: 9, + experience: 37.5, + item: { + itemId: itemIds.warhammers.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 24, + experience: 75, + item: { + itemId: itemIds.warhammers.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 39, + experience: 112.5, + item: { + itemId: itemIds.warhammers.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 59, + experience: 150, + item: { + itemId: itemIds.warhammers.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 79, + experience: 187.5, + item: { + itemId: itemIds.warhammers.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 94, + experience: 225, + item: { + itemId: itemIds.warhammers.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'battleaxe', + new Map([ + [ + 'bronze', + { + level: 9, + experience: 37.5, + item: { + itemId: itemIds.battleAxes.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 24, + experience: 75, + item: { + itemId: itemIds.battleAxes.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 39, + experience: 112.5, + item: { + itemId: itemIds.battleAxes.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 59, + experience: 150, + item: { + itemId: itemIds.battleAxes.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 79, + experience: 187.5, + item: { + itemId: itemIds.battleAxes.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 94, + experience: 225, + item: { + itemId: itemIds.battleAxes.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'chainbody', + new Map([ + [ + 'bronze', + { + level: 11, + experience: 37.5, + item: { + itemId: itemIds.chainbodies.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 26, + experience: 75, + item: { + itemId: itemIds.chainbodies.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 41, + experience: 112.5, + item: { + itemId: itemIds.chainbodies.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 61, + experience: 150, + item: { + itemId: itemIds.chainbodies.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 81, + experience: 187.5, + item: { + itemId: itemIds.chainbodies.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 96, + experience: 225, + item: { + itemId: itemIds.chainbodies.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'kiteshield', + new Map([ + [ + 'bronze', + { + level: 12, + experience: 37.5, + item: { + itemId: itemIds.kiteshields.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 27, + experience: 75, + item: { + itemId: itemIds.kiteshields.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 42, + experience: 112.5, + item: { + itemId: itemIds.kiteshields.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 62, + experience: 150, + item: { + itemId: itemIds.kiteshields.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 82, + experience: 187.5, + item: { + itemId: itemIds.kiteshields.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 97, + experience: 225, + item: { + itemId: itemIds.kiteshields.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'claws', + new Map([ + [ + 'bronze', + { + level: 13, + experience: 25, + item: { + itemId: itemIds.claws.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 2, + }, + }, + ], + [ + 'iron', + { + level: 28, + experience: 50, + item: { + itemId: itemIds.claws.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 2, + }, + }, + ], + [ + 'steel', + { + level: 43, + experience: 75, + item: { + itemId: itemIds.claws.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 2, + }, + }, + ], + [ + 'mithril', + { + level: 63, + experience: 100, + item: { + itemId: itemIds.claws.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 2, + }, + }, + ], + [ + 'adamant', + { + level: 83, + experience: 125, + item: { + itemId: itemIds.claws.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 2, + }, + }, + ], + [ + 'rune', + { + level: 98, + experience: 150, + item: { + itemId: itemIds.claws.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 2, + }, + }, + ], + ]), + ], + [ + 'twoHandedSword', + new Map([ + [ + 'bronze', + { + level: 14, + experience: 37.5, + item: { + itemId: itemIds.twoHandSwords.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 29, + experience: 75, + item: { + itemId: itemIds.twoHandSwords.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 44, + experience: 112.5, + item: { + itemId: itemIds.twoHandSwords.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 64, + experience: 150, + item: { + itemId: itemIds.twoHandSwords.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 84, + experience: 187.5, + item: { + itemId: itemIds.twoHandSwords.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 99, + experience: 225, + item: { + itemId: itemIds.twoHandSwords.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'platelegs', + new Map([ + [ + 'bronze', + { + level: 16, + experience: 37.5, + item: { + itemId: itemIds.platelegs.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 31, + experience: 75, + item: { + itemId: itemIds.platelegs.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 46, + experience: 112.5, + item: { + itemId: itemIds.platelegs.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 66, + experience: 150, + item: { + itemId: itemIds.platelegs.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 86, + experience: 187.5, + item: { + itemId: itemIds.platelegs.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 99, + experience: 225, + item: { + itemId: itemIds.platelegs.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'plateskirt', + new Map([ + [ + 'bronze', + { + level: 16, + experience: 37.5, + item: { + itemId: itemIds.plateskirts.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 3, + }, + }, + ], + [ + 'iron', + { + level: 31, + experience: 75, + item: { + itemId: itemIds.plateskirts.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 3, + }, + }, + ], + [ + 'steel', + { + level: 46, + experience: 112.5, + item: { + itemId: itemIds.plateskirts.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 3, + }, + }, + ], + [ + 'mithril', + { + level: 66, + experience: 150, + item: { + itemId: itemIds.plateskirts.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 3, + }, + }, + ], + [ + 'adamant', + { + level: 86, + experience: 187.5, + item: { + itemId: itemIds.plateskirts.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 3, + }, + }, + ], + [ + 'rune', + { + level: 99, + experience: 225, + item: { + itemId: itemIds.plateskirts.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 3, + }, + }, + ], + ]), + ], + [ + 'platebody', + new Map([ + [ + 'bronze', + { + level: 16, + experience: 37.5, + item: { + itemId: itemIds.platebodys.bronze, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 5, + }, + }, + ], + [ + 'iron', + { + level: 31, + experience: 75, + item: { + itemId: itemIds.platebodys.iron, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.iron, + amount: 5, + }, + }, + ], + [ + 'steel', + { + level: 46, + experience: 112.5, + item: { + itemId: itemIds.platebodys.steel, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.steel, + amount: 5, + }, + }, + ], + [ + 'mithril', + { + level: 66, + experience: 150, + item: { + itemId: itemIds.platebodys.mithril, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.mithril, + amount: 5, + }, + }, + ], + [ + 'adamant', + { + level: 86, + experience: 187.5, + item: { + itemId: itemIds.platebodys.adamantite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.adamantite, + amount: 5, + }, + }, + ], + [ + 'rune', + { + level: 99, + experience: 225, + item: { + itemId: itemIds.platebodys.runite, + amount: 1, + }, + ingredient: { + itemId: itemIds.bars.runite, + amount: 5, + }, + }, + ], + ]), + ], + [ + 'unknown', + new Map([ + [ + 'any', + { + level: 1, + experience: 0, + item: { + itemId: -1, + amount: -1, + }, + ingredient: { + itemId: itemIds.bars.bronze, + amount: 1, + }, + }, + ], + ]), + ], ]); /** * TODO (Jameskmonger) I ran a find-and-replace over this to stop TypeScript errors, recommend refactoring */ -export const widgetItems : Map> = new Map>([ - [itemIds.bars.bronze, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('bronze') as Smithable, - smithables.get('sword')?.get('bronze') as Smithable, - smithables.get('scimitar')?.get('bronze') as Smithable, - smithables.get('longsword')?.get('bronze') as Smithable, - smithables.get('twoHandedSword')?.get('bronze') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('bronze') as Smithable, - smithables.get('mace')?.get('bronze') as Smithable, - smithables.get('warhammer')?.get('bronze') as Smithable, - smithables.get('battleaxe')?.get('bronze') as Smithable, - smithables.get('claws')?.get('bronze') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('bronze') as Smithable, - smithables.get('platelegs')?.get('bronze') as Smithable, - smithables.get('plateskirt')?.get('bronze') as Smithable, - smithables.get('platebody')?.get('bronze') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('bronze') as Smithable, - smithables.get('fullHelm')?.get('bronze') as Smithable, - smithables.get('squareShield')?.get('bronze') as Smithable, - smithables.get('kiteshield')?.get('bronze') as Smithable, - smithables.get('nails')?.get('bronze') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('bronze') as Smithable, - smithables.get('arrowTips')?.get('bronze') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('bronze') as Smithable, - smithables.get('limbs')?.get('bronze') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])], - [itemIds.bars.iron, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('iron') as Smithable, - smithables.get('sword')?.get('iron') as Smithable, - smithables.get('scimitar')?.get('iron') as Smithable, - smithables.get('longsword')?.get('iron') as Smithable, - smithables.get('twoHandedSword')?.get('iron') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('iron') as Smithable, - smithables.get('mace')?.get('iron') as Smithable, - smithables.get('warhammer')?.get('iron') as Smithable, - smithables.get('battleaxe')?.get('iron') as Smithable, - smithables.get('claws')?.get('iron') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('iron') as Smithable, - smithables.get('platelegs')?.get('iron') as Smithable, - smithables.get('plateskirt')?.get('iron') as Smithable, - smithables.get('platebody')?.get('iron') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('iron') as Smithable, - smithables.get('fullHelm')?.get('iron') as Smithable, - smithables.get('squareShield')?.get('iron') as Smithable, - smithables.get('kiteshield')?.get('iron') as Smithable, - smithables.get('nails')?.get('iron') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('iron') as Smithable, - smithables.get('arrowTips')?.get('iron') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('iron') as Smithable, - smithables.get('limbs')?.get('iron') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])], - [itemIds.bars.steel, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('steel') as Smithable, - smithables.get('sword')?.get('steel') as Smithable, - smithables.get('scimitar')?.get('steel') as Smithable, - smithables.get('longsword')?.get('steel') as Smithable, - smithables.get('twoHandedSword')?.get('steel') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('steel') as Smithable, - smithables.get('mace')?.get('steel') as Smithable, - smithables.get('warhammer')?.get('steel') as Smithable, - smithables.get('battleaxe')?.get('steel') as Smithable, - smithables.get('claws')?.get('steel') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('steel') as Smithable, - smithables.get('platelegs')?.get('steel') as Smithable, - smithables.get('plateskirt')?.get('steel') as Smithable, - smithables.get('platebody')?.get('steel') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('steel') as Smithable, - smithables.get('fullHelm')?.get('steel') as Smithable, - smithables.get('squareShield')?.get('steel') as Smithable, - smithables.get('kiteshield')?.get('steel') as Smithable, - smithables.get('nails')?.get('steel') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('steel') as Smithable, - smithables.get('arrowTips')?.get('steel') as Smithable, - smithables.get('knife')?.get('steel') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('steel') as Smithable, - smithables.get('limbs')?.get('steel') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])], - [itemIds.bars.mithril, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('mithril') as Smithable, - smithables.get('sword')?.get('mithril') as Smithable, - smithables.get('scimitar')?.get('mithril') as Smithable, - smithables.get('longsword')?.get('mithril') as Smithable, - smithables.get('twoHandedSword')?.get('mithril') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('mithril') as Smithable, - smithables.get('mace')?.get('mithril') as Smithable, - smithables.get('warhammer')?.get('mithril') as Smithable, - smithables.get('battleaxe')?.get('mithril') as Smithable, - smithables.get('claws')?.get('mithril') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('mithril') as Smithable, - smithables.get('platelegs')?.get('mithril') as Smithable, - smithables.get('plateskirt')?.get('mithril') as Smithable, - smithables.get('platebody')?.get('mithril') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('mithril') as Smithable, - smithables.get('fullHelm')?.get('mithril') as Smithable, - smithables.get('squareShield')?.get('mithril') as Smithable, - smithables.get('kiteshield')?.get('mithril') as Smithable, - smithables.get('nails')?.get('mithril') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('mithril') as Smithable, - smithables.get('arrowTips')?.get('mithril') as Smithable, - smithables.get('knife')?.get('mithril') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('mithril') as Smithable, - smithables.get('limbs')?.get('mithril') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])], - [itemIds.bars.adamantite, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('adamant') as Smithable, - smithables.get('sword')?.get('adamant') as Smithable, - smithables.get('scimitar')?.get('adamant') as Smithable, - smithables.get('longsword')?.get('adamant') as Smithable, - smithables.get('twoHandedSword')?.get('adamant') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('adamant') as Smithable, - smithables.get('mace')?.get('adamant') as Smithable, - smithables.get('warhammer')?.get('adamant') as Smithable, - smithables.get('battleaxe')?.get('adamant') as Smithable, - smithables.get('claws')?.get('adamant') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('adamant') as Smithable, - smithables.get('platelegs')?.get('adamant') as Smithable, - smithables.get('plateskirt')?.get('adamant') as Smithable, - smithables.get('platebody')?.get('adamant') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('adamant') as Smithable, - smithables.get('fullHelm')?.get('adamant') as Smithable, - smithables.get('squareShield')?.get('adamant') as Smithable, - smithables.get('kiteshield')?.get('adamant') as Smithable, - smithables.get('nails')?.get('adamant') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('adamant') as Smithable, - smithables.get('arrowTips')?.get('adamant') as Smithable, - smithables.get('knife')?.get('adamant') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('adamant') as Smithable, - smithables.get('limbs')?.get('adamant') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])], - [itemIds.bars.runite, new Map([ - [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger')?.get('rune') as Smithable, - smithables.get('sword')?.get('rune') as Smithable, - smithables.get('scimitar')?.get('rune') as Smithable, - smithables.get('longsword')?.get('rune') as Smithable, - smithables.get('twoHandedSword')?.get('rune') as Smithable, - ]], - [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe')?.get('rune') as Smithable, - smithables.get('mace')?.get('rune') as Smithable, - smithables.get('warhammer')?.get('rune') as Smithable, - smithables.get('battleaxe')?.get('rune') as Smithable, - smithables.get('claws')?.get('rune') as Smithable - ]], - [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody')?.get('rune') as Smithable, - smithables.get('platelegs')?.get('rune') as Smithable, - smithables.get('plateskirt')?.get('rune') as Smithable, - smithables.get('platebody')?.get('rune') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm')?.get('rune') as Smithable, - smithables.get('fullHelm')?.get('rune') as Smithable, - smithables.get('squareShield')?.get('rune') as Smithable, - smithables.get('kiteshield')?.get('rune') as Smithable, - smithables.get('nails')?.get('rune') as Smithable - ]], - [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips')?.get('rune') as Smithable, - smithables.get('arrowTips')?.get('rune') as Smithable, - smithables.get('knife')?.get('rune') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - smithables.get('unknown')?.get('any') as Smithable - ]], - [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts')?.get('rune') as Smithable, - smithables.get('limbs')?.get('rune') as Smithable, - smithables.get('unknown')?.get('any') as Smithable, - ]] - ])] +export const widgetItems: Map> = new Map>([ + [ + itemIds.bars.bronze, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('bronze') as Smithable, + smithables.get('sword')?.get('bronze') as Smithable, + smithables.get('scimitar')?.get('bronze') as Smithable, + smithables.get('longsword')?.get('bronze') as Smithable, + smithables.get('twoHandedSword')?.get('bronze') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('bronze') as Smithable, + smithables.get('mace')?.get('bronze') as Smithable, + smithables.get('warhammer')?.get('bronze') as Smithable, + smithables.get('battleaxe')?.get('bronze') as Smithable, + smithables.get('claws')?.get('bronze') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('bronze') as Smithable, + smithables.get('platelegs')?.get('bronze') as Smithable, + smithables.get('plateskirt')?.get('bronze') as Smithable, + smithables.get('platebody')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('bronze') as Smithable, + smithables.get('fullHelm')?.get('bronze') as Smithable, + smithables.get('squareShield')?.get('bronze') as Smithable, + smithables.get('kiteshield')?.get('bronze') as Smithable, + smithables.get('nails')?.get('bronze') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('bronze') as Smithable, + smithables.get('arrowTips')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('bronze') as Smithable, + smithables.get('limbs')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], + [ + itemIds.bars.iron, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('iron') as Smithable, + smithables.get('sword')?.get('iron') as Smithable, + smithables.get('scimitar')?.get('iron') as Smithable, + smithables.get('longsword')?.get('iron') as Smithable, + smithables.get('twoHandedSword')?.get('iron') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('iron') as Smithable, + smithables.get('mace')?.get('iron') as Smithable, + smithables.get('warhammer')?.get('iron') as Smithable, + smithables.get('battleaxe')?.get('iron') as Smithable, + smithables.get('claws')?.get('iron') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('iron') as Smithable, + smithables.get('platelegs')?.get('iron') as Smithable, + smithables.get('plateskirt')?.get('iron') as Smithable, + smithables.get('platebody')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('iron') as Smithable, + smithables.get('fullHelm')?.get('iron') as Smithable, + smithables.get('squareShield')?.get('iron') as Smithable, + smithables.get('kiteshield')?.get('iron') as Smithable, + smithables.get('nails')?.get('iron') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('iron') as Smithable, + smithables.get('arrowTips')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('iron') as Smithable, + smithables.get('limbs')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], + [ + itemIds.bars.steel, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('steel') as Smithable, + smithables.get('sword')?.get('steel') as Smithable, + smithables.get('scimitar')?.get('steel') as Smithable, + smithables.get('longsword')?.get('steel') as Smithable, + smithables.get('twoHandedSword')?.get('steel') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('steel') as Smithable, + smithables.get('mace')?.get('steel') as Smithable, + smithables.get('warhammer')?.get('steel') as Smithable, + smithables.get('battleaxe')?.get('steel') as Smithable, + smithables.get('claws')?.get('steel') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('steel') as Smithable, + smithables.get('platelegs')?.get('steel') as Smithable, + smithables.get('plateskirt')?.get('steel') as Smithable, + smithables.get('platebody')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('steel') as Smithable, + smithables.get('fullHelm')?.get('steel') as Smithable, + smithables.get('squareShield')?.get('steel') as Smithable, + smithables.get('kiteshield')?.get('steel') as Smithable, + smithables.get('nails')?.get('steel') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('steel') as Smithable, + smithables.get('arrowTips')?.get('steel') as Smithable, + smithables.get('knife')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('steel') as Smithable, + smithables.get('limbs')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], + [ + itemIds.bars.mithril, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('mithril') as Smithable, + smithables.get('sword')?.get('mithril') as Smithable, + smithables.get('scimitar')?.get('mithril') as Smithable, + smithables.get('longsword')?.get('mithril') as Smithable, + smithables.get('twoHandedSword')?.get('mithril') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('mithril') as Smithable, + smithables.get('mace')?.get('mithril') as Smithable, + smithables.get('warhammer')?.get('mithril') as Smithable, + smithables.get('battleaxe')?.get('mithril') as Smithable, + smithables.get('claws')?.get('mithril') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('mithril') as Smithable, + smithables.get('platelegs')?.get('mithril') as Smithable, + smithables.get('plateskirt')?.get('mithril') as Smithable, + smithables.get('platebody')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('mithril') as Smithable, + smithables.get('fullHelm')?.get('mithril') as Smithable, + smithables.get('squareShield')?.get('mithril') as Smithable, + smithables.get('kiteshield')?.get('mithril') as Smithable, + smithables.get('nails')?.get('mithril') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('mithril') as Smithable, + smithables.get('arrowTips')?.get('mithril') as Smithable, + smithables.get('knife')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('mithril') as Smithable, + smithables.get('limbs')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], + [ + itemIds.bars.adamantite, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('adamant') as Smithable, + smithables.get('sword')?.get('adamant') as Smithable, + smithables.get('scimitar')?.get('adamant') as Smithable, + smithables.get('longsword')?.get('adamant') as Smithable, + smithables.get('twoHandedSword')?.get('adamant') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('adamant') as Smithable, + smithables.get('mace')?.get('adamant') as Smithable, + smithables.get('warhammer')?.get('adamant') as Smithable, + smithables.get('battleaxe')?.get('adamant') as Smithable, + smithables.get('claws')?.get('adamant') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('adamant') as Smithable, + smithables.get('platelegs')?.get('adamant') as Smithable, + smithables.get('plateskirt')?.get('adamant') as Smithable, + smithables.get('platebody')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('adamant') as Smithable, + smithables.get('fullHelm')?.get('adamant') as Smithable, + smithables.get('squareShield')?.get('adamant') as Smithable, + smithables.get('kiteshield')?.get('adamant') as Smithable, + smithables.get('nails')?.get('adamant') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('adamant') as Smithable, + smithables.get('arrowTips')?.get('adamant') as Smithable, + smithables.get('knife')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('adamant') as Smithable, + smithables.get('limbs')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], + [ + itemIds.bars.runite, + new Map([ + [ + 146, + [ + // Dagger, Sword, Scimitar, Longsword, 2h sword + smithables.get('dagger')?.get('rune') as Smithable, + smithables.get('sword')?.get('rune') as Smithable, + smithables.get('scimitar')?.get('rune') as Smithable, + smithables.get('longsword')?.get('rune') as Smithable, + smithables.get('twoHandedSword')?.get('rune') as Smithable, + ], + ], + [ + 147, + [ + // Axe, Mace, Warhammer, Battleaxe, Claws + smithables.get('axe')?.get('rune') as Smithable, + smithables.get('mace')?.get('rune') as Smithable, + smithables.get('warhammer')?.get('rune') as Smithable, + smithables.get('battleaxe')?.get('rune') as Smithable, + smithables.get('claws')?.get('rune') as Smithable, + ], + ], + [ + 148, + [ + // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* + smithables.get('chainbody')?.get('rune') as Smithable, + smithables.get('platelegs')?.get('rune') as Smithable, + smithables.get('plateskirt')?.get('rune') as Smithable, + smithables.get('platebody')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 149, + [ + // Medium helm, Full helm, Sq shield, kite shield, Nails + smithables.get('mediumHelm')?.get('rune') as Smithable, + smithables.get('fullHelm')?.get('rune') as Smithable, + smithables.get('squareShield')?.get('rune') as Smithable, + smithables.get('kiteshield')?.get('rune') as Smithable, + smithables.get('nails')?.get('rune') as Smithable, + ], + ], + [ + 150, + [ + // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* + smithables.get('dartTips')?.get('rune') as Smithable, + smithables.get('arrowTips')?.get('rune') as Smithable, + smithables.get('knife')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + [ + 151, + [ + // Bolts, Limbs, Grapple tips + smithables.get('bolts')?.get('rune') as Smithable, + smithables.get('limbs')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + ], + ], + ]), + ], ]); diff --git a/src/plugins/skills/smithing/forging-task.ts b/src/plugins/skills/smithing/forging-task.ts index 0f48d5f07..a6e95eda6 100644 --- a/src/plugins/skills/smithing/forging-task.ts +++ b/src/plugins/skills/smithing/forging-task.ts @@ -1,8 +1,8 @@ import { widgets } from '@engine/config/config-handler'; -import type { Smithable } from './forging-types'; import { ActorTask } from '@engine/task/impl/actor-task'; import type { Player } from '@engine/world/actor/player/player'; import { Skill } from '@engine/world/actor/skills'; +import type { Smithable } from './forging-types'; /** * A task that handles the forging of an item. @@ -15,7 +15,11 @@ export class ForgingTask extends ActorTask { private elapsedTicks = 0; private amountForged = 0; - constructor(player: Player, private readonly smithable: Smithable, private readonly amount: number) { + constructor( + player: Player, + private readonly smithable: Smithable, + private readonly amount: number, + ) { super(player); } @@ -51,7 +55,7 @@ export class ForgingTask extends ActorTask { // Add item to inventory this.actor.inventory.add({ itemId: this.smithable.item.itemId, - amount: this.smithable.item.amount + amount: this.smithable.item.amount, }); this.actor.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.actor.inventory); @@ -65,6 +69,6 @@ export class ForgingTask extends ActorTask { * @returns {boolean} True if the player has the required materials, false otherwise. */ private hasMaterials() { - return this.smithable.ingredient.amount <= this.actor.inventory.findAll(this.smithable.ingredient.itemId).length + return this.smithable.ingredient.amount <= this.actor.inventory.findAll(this.smithable.ingredient.itemId).length; } } diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index 5c3ffc1f1..6d79b8b47 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -1,15 +1,15 @@ +import type { ItemInteractionActionHook } from '@engine/action/pipe/item-interaction.action'; +import type { ItemOnObjectActionHook, itemOnObjectActionHandler } from '@engine/action/pipe/item-on-object.action'; import { widgets } from '@engine/config/config-handler'; +import { findItem } from '@engine/config/config-handler'; +import type { Player } from '@engine/world/actor/player/player'; import { Skill } from '@engine/world/actor/skills'; -import { anvilIds, bars, smithables, widgetItems } from '@plugins/skills/smithing/forging-constants'; import { itemIds } from '@engine/world/config/item-ids'; -import type { Smithable } from '@plugins/skills/smithing/forging-types'; -import type { Player } from '@engine/world/actor/player/player'; -import { findItem } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; -import { ForgingTask } from './forging-task'; +import { anvilIds, bars, smithables, widgetItems } from '@plugins/skills/smithing/forging-constants'; +import type { Smithable } from '@plugins/skills/smithing/forging-types'; import { logger } from '@runejs/common'; -import type { ItemInteractionActionHook } from '@engine/action/pipe/item-interaction.action'; -import type { itemOnObjectActionHandler, ItemOnObjectActionHook } from '@engine/action/pipe/item-on-object.action'; +import { ForgingTask } from './forging-task'; /** * Get the item ids of all the smithable items, as a flat array. @@ -21,8 +21,8 @@ import type { itemOnObjectActionHandler, ItemOnObjectActionHook } from '@engine/ */ const mapSmithableItemIdsToFlatArray = (input: Map>) => { const result: number[] = []; - input.forEach((type) => { - type.forEach((smithable) => { + input.forEach(type => { + type.forEach(smithable => { result.push(smithable.item.itemId); }); }); @@ -42,8 +42,8 @@ const mapSmithableItemIdsToFlatArray = (input: Map>) => { const results: Smithable[] = []; - input.forEach((values) => { - values.forEach((value) => { + input.forEach(values => { + values.forEach(value => { results.push(value); }); }); @@ -54,10 +54,12 @@ const mapSmithablesToFlatArray = (input: Map>) => * Lookup a smithable from just an item id. * @param itemId */ -const findSmithableByItemId = (itemId: number) : Smithable | null => { - return mapSmithablesToFlatArray(smithables).find((smithable) => { - return smithable.item.itemId === itemId; - }) || null; +const findSmithableByItemId = (itemId: number): Smithable | null => { + return ( + mapSmithablesToFlatArray(smithables).find(smithable => { + return smithable.item.itemId === itemId; + }) || null + ); }; /** @@ -113,7 +115,7 @@ const hasMaterials = (player: Player, smithable: Smithable) => { * Opens the forging interface, and loads the items. * @param details */ -const openForgingInterface: itemOnObjectActionHandler = (details) => { +const openForgingInterface: itemOnObjectActionHandler = details => { const { player, item, object } = details; const amountInInventory = player.inventory.findAll(item).length; @@ -148,7 +150,7 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => { player.outgoingPackets.updateClientConfig(211, player.skills.getLevel(Skill.SMITHING)); details.player.interfaceState.openWidget(widgets.anvil.widgetId, { - slot: 'screen' + slot: 'screen', }); const barWidgetItems = widgetItems.get(item.itemId); @@ -160,9 +162,14 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => { barWidgetItems.forEach((items, containerId) => { items.forEach((smithable, index) => { - player.outgoingPackets.sendUpdateSingleWidgetItem({ - widgetId: widgets.anvil.widgetId, containerId: containerId - }, index, smithable.item); + player.outgoingPackets.sendUpdateSingleWidgetItem( + { + widgetId: widgets.anvil.widgetId, + containerId: containerId, + }, + index, + smithable.item, + ); }); }); }; @@ -177,7 +184,7 @@ export default { walkTo: true, cancelOtherActions: true, - handler: openForgingInterface + handler: openForgingInterface, } as ItemOnObjectActionHook, { type: 'item_interaction', @@ -196,9 +203,15 @@ export default { let wantedAmount = 0; switch (option) { - case 'make': wantedAmount = 1; break; - case 'make-5': wantedAmount = 5; break; - case 'make-10': wantedAmount = 10; break; + case 'make': + wantedAmount = 1; + break; + case 'make-5': + wantedAmount = 5; + break; + case 'make-10': + wantedAmount = 10; + break; } if (!canForge(player, smithable)) { @@ -206,7 +219,7 @@ export default { } player.enqueueTask(ForgingTask, [smithable, wantedAmount]); - } - } as ItemInteractionActionHook - ] + }, + } as ItemInteractionActionHook, + ], }; diff --git a/src/plugins/skills/smithing/smelting-constants.ts b/src/plugins/skills/smithing/smelting-constants.ts index eaa20127d..01c1188b2 100644 --- a/src/plugins/skills/smithing/smelting-constants.ts +++ b/src/plugins/skills/smithing/smelting-constants.ts @@ -2,91 +2,83 @@ import { widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; import type { Bar, Smeltable } from '@plugins/skills/smithing/smelting-types'; -const BRONZE : Bar = { +const BRONZE: Bar = { barId: itemIds.bars.bronze, requiredLevel: 1, experience: 6.2, ingredients: [ { itemId: itemIds.ores.copper, amount: 1 }, - { itemId: itemIds.ores.tin, amount: 1 } - ] + { itemId: itemIds.ores.tin, amount: 1 }, + ], }; -const BLURITE : Bar = { +const BLURITE: Bar = { barId: itemIds.bars.blurite, quest: 'theKnightsSword', requiredLevel: 8, experience: 8, - ingredients: [ - { itemId: itemIds.ores.blurite, amount: 1 } - ] + ingredients: [{ itemId: itemIds.ores.blurite, amount: 1 }], }; -const IRON : Bar = { +const IRON: Bar = { barId: itemIds.bars.iron, requiredLevel: 15, experience: 12.5, - ingredients: [ - { itemId: itemIds.ores.iron, amount: 1 } - ] + ingredients: [{ itemId: itemIds.ores.iron, amount: 1 }], }; -const SILVER : Bar = { +const SILVER: Bar = { barId: itemIds.bars.silver, requiredLevel: 20, experience: 13.6, - ingredients: [ - { itemId: itemIds.ores.silver, amount: 1 } - ] + ingredients: [{ itemId: itemIds.ores.silver, amount: 1 }], }; -const STEEL : Bar = { +const STEEL: Bar = { barId: itemIds.bars.steel, requiredLevel: 30, experience: 17.5, ingredients: [ { itemId: itemIds.ores.iron, amount: 1 }, - { itemId: itemIds.ores.coal, amount: 2 } - ] + { itemId: itemIds.ores.coal, amount: 2 }, + ], }; -const GOLD : Bar = { +const GOLD: Bar = { barId: itemIds.bars.gold, requiredLevel: 40, experience: 22.5, - ingredients: [ - { itemId: itemIds.ores.gold, amount: 1 } - ] + ingredients: [{ itemId: itemIds.ores.gold, amount: 1 }], }; -const MITHRIL : Bar = { +const MITHRIL: Bar = { barId: itemIds.bars.mithril, requiredLevel: 50, experience: 30, ingredients: [ { itemId: itemIds.ores.mithril, amount: 1 }, { itemId: itemIds.ores.coal, amount: 4 }, - ] + ], }; -const ADAMANTITE : Bar = { +const ADAMANTITE: Bar = { barId: itemIds.bars.adamantite, requiredLevel: 70, experience: 37.5, ingredients: [ { itemId: itemIds.ores.adamantite, amount: 1 }, { itemId: itemIds.ores.coal, amount: 6 }, - ] + ], }; -const RUNEITE : Bar = { +const RUNEITE: Bar = { barId: itemIds.bars.runite, requiredLevel: 85, experience: 50, ingredients: [ { itemId: itemIds.ores.runite, amount: 1 }, { itemId: itemIds.ores.coal, amount: 8 }, - ] + ], }; export const widgetItems = [ @@ -97,47 +89,47 @@ export const widgetItems = [ { slot: widgets.furnace.slots.slot5, bar: GOLD }, { slot: widgets.furnace.slots.slot6, bar: MITHRIL }, { slot: widgets.furnace.slots.slot7, bar: ADAMANTITE }, - { slot: widgets.furnace.slots.slot8, bar: RUNEITE } + { slot: widgets.furnace.slots.slot8, bar: RUNEITE }, ]; /** * Defines the widget button ids. */ -export const widgetButtonIds : Map = new Map([ - [16, { takesInput: false, count: 1, bar: BRONZE }], - [15, { takesInput: false, count: 5, bar: BRONZE }], +export const widgetButtonIds: Map = new Map([ + [16, { takesInput: false, count: 1, bar: BRONZE }], + [15, { takesInput: false, count: 5, bar: BRONZE }], [14, { takesInput: false, count: 10, bar: BRONZE }], - [13, { takesInput: true, count: 0, bar: BRONZE }], - [20, { takesInput: false, count: 1, bar: BLURITE }], - [19, { takesInput: false, count: 5, bar: BLURITE }], + [13, { takesInput: true, count: 0, bar: BRONZE }], + [20, { takesInput: false, count: 1, bar: BLURITE }], + [19, { takesInput: false, count: 5, bar: BLURITE }], [18, { takesInput: false, count: 10, bar: BLURITE }], - [17, { takesInput: true, count: 0, bar: BLURITE }], - [24, { takesInput: false, count: 1, bar: IRON }], - [23, { takesInput: false, count: 5, bar: IRON }], + [17, { takesInput: true, count: 0, bar: BLURITE }], + [24, { takesInput: false, count: 1, bar: IRON }], + [23, { takesInput: false, count: 5, bar: IRON }], [22, { takesInput: false, count: 10, bar: IRON }], - [21, { takesInput: true, count: 0, bar: IRON }], - [28, { takesInput: false, count: 1, bar: SILVER }], - [27, { takesInput: false, count: 5, bar: SILVER }], + [21, { takesInput: true, count: 0, bar: IRON }], + [28, { takesInput: false, count: 1, bar: SILVER }], + [27, { takesInput: false, count: 5, bar: SILVER }], [26, { takesInput: false, count: 10, bar: SILVER }], - [25, { takesInput: true, count: 0, bar: SILVER }], - [32, { takesInput: false, count: 1, bar: STEEL }], - [31, { takesInput: false, count: 5, bar: STEEL }], + [25, { takesInput: true, count: 0, bar: SILVER }], + [32, { takesInput: false, count: 1, bar: STEEL }], + [31, { takesInput: false, count: 5, bar: STEEL }], [30, { takesInput: false, count: 10, bar: STEEL }], - [29, { takesInput: true, count: 0, bar: STEEL }], - [36, { takesInput: false, count: 1, bar: GOLD }], - [35, { takesInput: false, count: 5, bar: GOLD }], + [29, { takesInput: true, count: 0, bar: STEEL }], + [36, { takesInput: false, count: 1, bar: GOLD }], + [35, { takesInput: false, count: 5, bar: GOLD }], [34, { takesInput: false, count: 10, bar: GOLD }], - [33, { takesInput: true, count: 0, bar: GOLD }], - [40, { takesInput: false, count: 1, bar: MITHRIL }], - [39, { takesInput: false, count: 5, bar: MITHRIL }], + [33, { takesInput: true, count: 0, bar: GOLD }], + [40, { takesInput: false, count: 1, bar: MITHRIL }], + [39, { takesInput: false, count: 5, bar: MITHRIL }], [38, { takesInput: false, count: 10, bar: MITHRIL }], - [37, { takesInput: true, count: 0, bar: MITHRIL }], - [44, { takesInput: false, count: 1, bar: ADAMANTITE }], - [43, { takesInput: false, count: 5, bar: ADAMANTITE }], + [37, { takesInput: true, count: 0, bar: MITHRIL }], + [44, { takesInput: false, count: 1, bar: ADAMANTITE }], + [43, { takesInput: false, count: 5, bar: ADAMANTITE }], [42, { takesInput: false, count: 10, bar: ADAMANTITE }], - [41, { takesInput: true, count: 0, bar: ADAMANTITE }], - [48, { takesInput: false, count: 1, bar: RUNEITE }], - [47, { takesInput: false, count: 5, bar: RUNEITE }], + [41, { takesInput: true, count: 0, bar: ADAMANTITE }], + [48, { takesInput: false, count: 1, bar: RUNEITE }], + [47, { takesInput: false, count: 5, bar: RUNEITE }], [46, { takesInput: false, count: 10, bar: RUNEITE }], - [45, { takesInput: true, count: 0, bar: RUNEITE }] + [45, { takesInput: true, count: 0, bar: RUNEITE }], ]); diff --git a/src/plugins/skills/smithing/smelting-task.ts b/src/plugins/skills/smithing/smelting-task.ts index 296205d14..7c31df5b8 100644 --- a/src/plugins/skills/smithing/smelting-task.ts +++ b/src/plugins/skills/smithing/smelting-task.ts @@ -1,10 +1,10 @@ import { findItem } from '@engine/config/config-handler'; -import type { Smeltable } from './smelting-types'; import { ActorTask } from '@engine/task/impl/actor-task'; import type { Player } from '@engine/world/actor/player/player'; import { Skill } from '@engine/world/actor/skills'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; +import type { Smeltable } from './smelting-types'; /** * A task that handles the smelting of an item. @@ -15,9 +15,13 @@ import { soundIds } from '@engine/world/config/sound-ids'; */ export class SmeltingTask extends ActorTask { private elapsedTicks = 0; - private amountSmelted = 0 + private amountSmelted = 0; - constructor(player: Player, private readonly smeltable: Smeltable, private readonly amount: number) { + constructor( + player: Player, + private readonly smeltable: Smeltable, + private readonly amount: number, + ) { super(player); } @@ -55,7 +59,7 @@ export class SmeltingTask extends ActorTask { return; } - bar.ingredients.forEach((item) => { + bar.ingredients.forEach(item => { for (let i = 0; i < item.amount; i++) { this.actor.removeFirstItem(item.itemId); } @@ -74,7 +78,7 @@ export class SmeltingTask extends ActorTask { * @returns {boolean} True if the player has the required materials, false otherwise. */ private hasMaterials() { - return this.smeltable.bar.ingredients.every((item) => { + return this.smeltable.bar.ingredients.every(item => { const itemIndex = this.actor.inventory.findIndex(item); if (itemIndex === -1 || this.actor.inventory.amountInStack(itemIndex) < item.amount) { return false; diff --git a/src/plugins/skills/smithing/smelting.plugin.ts b/src/plugins/skills/smithing/smelting.plugin.ts index 91d08e027..97b403555 100644 --- a/src/plugins/skills/smithing/smelting.plugin.ts +++ b/src/plugins/skills/smithing/smelting.plugin.ts @@ -1,17 +1,20 @@ -import { objectIds } from '@engine/world/config/object-ids'; -import { Skill } from '@engine/world/actor/skills'; -import { colors } from '@engine/util/colors'; +import type { ButtonActionHook, buttonActionHandler } from '@engine/action/pipe/button.action'; +import type { + ObjectInteractionAction, + ObjectInteractionActionHook, + objectInteractionActionHandler, +} from '@engine/action/pipe/object-interaction.action'; import { widgets } from '@engine/config/config-handler'; +import { colors } from '@engine/util/colors'; +import { Skill } from '@engine/world/actor/skills'; +import { objectIds } from '@engine/world/config/object-ids'; import { widgetButtonIds, widgetItems } from '@plugins/skills/smithing/smelting-constants'; import { SmeltingTask } from './smelting-task'; -import type { buttonActionHandler, ButtonActionHook } from '@engine/action/pipe/button.action'; -import type { objectInteractionActionHandler, ObjectInteractionAction, ObjectInteractionActionHook } from '@engine/action/pipe/object-interaction.action'; - -export const openSmeltingInterface: objectInteractionActionHandler = (details) => { +export const openSmeltingInterface: objectInteractionActionHandler = details => { details.player.interfaceState.openWidget(widgets.furnace.widgetId, { - slot: 'chatbox' - }) + slot: 'chatbox', + }); loadSmeltingInterface(details); }; @@ -20,7 +23,7 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { const theKnightsSwordQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); // Send the items to the widget. - widgetItems.forEach((item) => { + widgetItems.forEach(item => { details.player.outgoingPackets.setItemOnWidget(widgets.furnace.widgetId, item.slot.modelId, item.bar.barId, 125); if (!details.player.skills.hasLevel(Skill.SMITHING, item.bar.requiredLevel)) { details.player.modifyWidget(widgets.furnace.widgetId, { childId: item.slot.titleId, textColor: colors.red }); @@ -28,7 +31,6 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { details.player.modifyWidget(widgets.furnace.widgetId, { childId: item.slot.titleId, textColor: colors.black }); } - // TODO (Jameskmonger) I don't think that this logic is correct.. it targets all items, not just those related to the quest. // Check if the player has completed 'The Knight's Sword' quest, even if the level is okay. if (Boolean(item.bar.quest) && (!theKnightsSwordQuest || theKnightsSwordQuest.complete)) { @@ -37,7 +39,7 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { }); }; -export const buttonClicked: buttonActionHandler = (details) => { +export const buttonClicked: buttonActionHandler = details => { // Check if player might be spawning widget clientside // TODO - this should be handled by the engine if (!details.player.interfaceState.findWidget(widgets.furnace.widgetId)) { @@ -65,7 +67,7 @@ export const buttonClicked: buttonActionHandler = (details) => { return; } - const numericInputSpinSubscription = details.player.numericInputEvent.subscribe((number) => { + const numericInputSpinSubscription = details.player.numericInputEvent.subscribe(number => { actionCancelledSpinSubscription?.unsubscribe(); numericInputSpinSubscription?.unsubscribe(); @@ -88,13 +90,13 @@ export default { objectIds: [objectIds.furnace, 11666], options: ['smelt'], walkTo: true, - handler: openSmeltingInterface + handler: openSmeltingInterface, } as ObjectInteractionActionHook, { type: 'button', widgetId: widgets.furnace.widgetId, buttonIds: Array.from(widgetButtonIds.keys()), - handler: buttonClicked - } as ButtonActionHook - ] + handler: buttonClicked, + } as ButtonActionHook, + ], }; diff --git a/src/plugins/skills/woodcutting/chance.ts b/src/plugins/skills/woodcutting/chance.ts index 7d09a4063..4bd30d5a4 100644 --- a/src/plugins/skills/woodcutting/chance.ts +++ b/src/plugins/skills/woodcutting/chance.ts @@ -10,14 +10,9 @@ import type { IHarvestable } from '@engine/world/config/harvestable-object'; * * @returns True if the tree was successfully cut, false otherwise */ -export const canCut = ( - tree: IHarvestable, - toolLevel: number, - woodcuttingLevel: number -): boolean => { +export const canCut = (tree: IHarvestable, toolLevel: number, woodcuttingLevel: number): boolean => { const successChance = randomBetween(0, 255); - const percentNeeded = - tree.baseChance + toolLevel + woodcuttingLevel; + const percentNeeded = tree.baseChance + toolLevel + woodcuttingLevel; return successChance <= percentNeeded; }; diff --git a/src/plugins/skills/woodcutting/index.ts b/src/plugins/skills/woodcutting/index.ts index e13add48a..81a7e0d41 100644 --- a/src/plugins/skills/woodcutting/index.ts +++ b/src/plugins/skills/woodcutting/index.ts @@ -1,6 +1,6 @@ +import type { ObjectInteractionActionHook } from '@engine/action/pipe/object-interaction.action'; import { getTreeIds } from '@engine/world/config/harvestable-object'; import { runWoodcuttingTask } from './woodcutting-task'; -import type { ObjectInteractionActionHook } from '@engine/action/pipe/object-interaction.action'; /** * Woodcutting plugin @@ -15,11 +15,11 @@ export default { */ { type: 'object_interaction', - options: [ 'chop down', 'chop' ], + options: ['chop down', 'chop'], objectIds: getTreeIds(), handler: ({ player, object }) => { runWoodcuttingTask(player, object); - } - } as ObjectInteractionActionHook - ] + }, + } as ObjectInteractionActionHook, + ], }; diff --git a/src/plugins/skills/woodcutting/woodcutting-task.ts b/src/plugins/skills/woodcutting/woodcutting-task.ts index 0a38fc950..758a913db 100644 --- a/src/plugins/skills/woodcutting/woodcutting-task.ts +++ b/src/plugins/skills/woodcutting/woodcutting-task.ts @@ -1,19 +1,19 @@ +import { findItem, findObject } from '@engine/config/config-handler'; +import { ActorLandscapeObjectInteractionTask } from '@engine/task/impl/actor-landscape-object-interaction-task'; +import { colors } from '@engine/util/colors'; +import { randomBetween } from '@engine/util/num'; +import { colorText } from '@engine/util/strings'; +import { activeWorld } from '@engine/world'; +import type { Player } from '@engine/world/actor/player/player'; import { Skill } from '@engine/world/actor/skills'; -import { canInitiateHarvest } from '@engine/world/skill-util/harvest-skill'; import type { IHarvestable } from '@engine/world/config/harvestable-object'; import { getTreeFromHealthy } from '@engine/world/config/harvestable-object'; -import { randomBetween } from '@engine/util/num'; -import { colorText } from '@engine/util/strings'; -import { colors } from '@engine/util/colors'; -import { rollBirdsNestType } from '@engine/world/skill-util/harvest-roll'; import { soundIds } from '@engine/world/config/sound-ids'; -import { findItem, findObject } from '@engine/config/config-handler'; -import { canCut } from './chance'; -import type { LandscapeObject } from '@runejs/filestore'; +import { rollBirdsNestType } from '@engine/world/skill-util/harvest-roll'; +import { canInitiateHarvest } from '@engine/world/skill-util/harvest-skill'; import { logger } from '@runejs/common'; -import { ActorLandscapeObjectInteractionTask } from '@engine/task/impl/actor-landscape-object-interaction-task'; -import type { Player } from '@engine/world/actor/player/player'; -import { activeWorld } from '@engine/world'; +import type { LandscapeObject } from '@runejs/filestore'; +import { canCut } from './chance'; class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { /** @@ -34,18 +34,8 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { * @param sizeX The size of the tree in x axis. * @param sizeY The size of the tree in y axis. */ - constructor( - player: Player, - landscapeObject: LandscapeObject, - sizeX: number, - sizeY: number - ) { - super( - player, - landscapeObject, - sizeX, - sizeY - ); + constructor(player: Player, landscapeObject: LandscapeObject, sizeX: number, sizeY: number) { + super(player, landscapeObject, sizeX, sizeY); if (!landscapeObject) { this.stop(); @@ -104,7 +94,7 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { return; } - if(taskIteration === 0) { + if (taskIteration === 0) { this.actor.sendMessage('You swing your axe at the tree.'); this.actor.face(this.landscapeObjectPosition); this.actor.playAnimation(tool.animation); @@ -114,18 +104,12 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { // play a random axe sound at the correct time if (taskIteration % 3 !== 0) { - const randomSoundIdx = Math.floor( - Math.random() * soundIds.axeSwing.length, - ); + const randomSoundIdx = Math.floor(Math.random() * soundIds.axeSwing.length); this.actor.playSound(soundIds.axeSwing[randomSoundIdx], 7, 0); } // roll for success - const succeeds = canCut( - this.treeInfo, - tool.level, - this.actor.skills.woodcutting.level, - ); + const succeeds = canCut(this.treeInfo, tool.level, this.actor.skills.woodcutting.level); if (!succeeds) { this.actor.playAnimation(tool.animation); @@ -153,7 +137,7 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { const targetName = (logItem.name || '').toLowerCase(); // if player doesn't have space in inventory, stop the task - if(!this.actor.inventory.hasSpace()) { + if (!this.actor.inventory.hasSpace()) { this.actor.sendMessage(`Your inventory is too full to hold any more ${targetName}.`, true); this.actor.playSound(soundIds.inventoryFull); this.stop(); @@ -162,11 +146,14 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { const roll = randomBetween(1, 256); // roll for bird nest chance - if(roll === 1) { + if (roll === 1) { this.actor.sendMessage(colorText(`A bird's nest falls out of the tree.`, colors.red)); - activeWorld.globalInstance.spawnWorldItem(rollBirdsNestType(), this.actor.position, - { owner: this.actor || null, expires: 300 }); - } else { // Standard log chopper + activeWorld.globalInstance.spawnWorldItem(rollBirdsNestType(), this.actor.position, { + owner: this.actor || null, + expires: 300, + }); + } else { + // Standard log chopper this.actor.sendMessage(`You manage to chop some ${targetName}.`); this.actor.giveItem(itemConfigId); } @@ -174,15 +161,18 @@ class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { this.actor.skills.woodcutting.addExp(this.treeInfo.experience); // check if the tree should be broken - if(randomBetween(0, 100) <= this.treeInfo.break) { + if (randomBetween(0, 100) <= this.treeInfo.break) { // TODO (Jameskmonger) is this the correct sound? this.actor.playSound(soundIds.oreDepeleted); const brokenTreeId = this.treeInfo.objects.get(this.landscapeObject.objectId); if (brokenTreeId !== undefined) { - this.actor.instance.replaceGameObject(brokenTreeId, - this.landscapeObject, randomBetween(this.treeInfo.respawnLow, this.treeInfo.respawnHigh)); + this.actor.instance.replaceGameObject( + brokenTreeId, + this.landscapeObject, + randomBetween(this.treeInfo.respawnLow, this.treeInfo.respawnHigh), + ); } else { logger.error(`Could not find broken tree id for tree id ${this.landscapeObject.objectId}`); } @@ -212,5 +202,5 @@ export function runWoodcuttingTask(player: Player, landscapeObject: LandscapeObj const sizeX = objectConfig.rendering.sizeX; const sizeY = objectConfig.rendering.sizeY; - player.enqueueTask(WoodcuttingTask, [ landscapeObject, sizeX, sizeY ]); + player.enqueueTask(WoodcuttingTask, [landscapeObject, sizeX, sizeY]); } diff --git a/src/server/game/game-server-connection.ts b/src/server/game/game-server-connection.ts index 39e67a7b4..aee13a92e 100644 --- a/src/server/game/game-server-connection.ts +++ b/src/server/game/game-server-connection.ts @@ -1,29 +1,29 @@ import type { Socket } from 'net'; +import { handlePacket, incomingPackets } from '@engine/net/inbound-packet-handler'; +import type { Player } from '@engine/world/actor/player/player'; import { logger } from '@runejs/common'; import { ByteBuffer } from '@runejs/common'; -import type { Player } from '@engine/world/actor/player/player'; -import { handlePacket, incomingPackets } from '@engine/net/inbound-packet-handler'; export class GameServerConnection { - private activePacketId: number | null = null; private activePacketSize: number | null = null; private activeBuffer: ByteBuffer | null; - public constructor(private readonly clientSocket: Socket, - private readonly player: Player) { - } + public constructor( + private readonly clientSocket: Socket, + private readonly player: Player, + ) {} public decodeMessage(buffer?: ByteBuffer): void | Promise { - if(!this.activeBuffer) { + if (!this.activeBuffer) { if (!buffer) { logger.error(`No buffer provided to decodeMessage.`); return; } else { this.activeBuffer = buffer; } - } else if(buffer) { + } else if (buffer) { const readable = this.activeBuffer.readable; const newBuffer = new ByteBuffer(readable + buffer.length); this.activeBuffer.copy(newBuffer, 0, this.activeBuffer.readerIndex); @@ -31,25 +31,25 @@ export class GameServerConnection { this.activeBuffer = newBuffer; } - if(this.activePacketId === null) { + if (this.activePacketId === null) { this.activePacketId = -1; } - if(this.activePacketSize === null) { + if (this.activePacketSize === null) { this.activePacketSize = -1; } const inCipher = this.player.inCipher; - if(this.activePacketId === -1) { - if(this.activeBuffer.readable < 1) { + if (this.activePacketId === -1) { + if (this.activeBuffer.readable < 1) { return; } this.activePacketId = this.activeBuffer.get('byte', 'u'); this.activePacketId = (this.activePacketId - inCipher.rand()) & 0xff; const incomingPacket = incomingPackets.get(this.activePacketId); - if(incomingPacket) { + if (incomingPacket) { this.activePacketSize = incomingPacket.size; } else { this.activePacketSize = -3; @@ -57,8 +57,8 @@ export class GameServerConnection { } // Packet will provide the size - if(this.activePacketSize === -1) { - if(this.activeBuffer.readable < 1) { + if (this.activePacketSize === -1) { + if (this.activeBuffer.readable < 1) { return; } @@ -67,8 +67,8 @@ export class GameServerConnection { // Packet has no set size let clearBuffer = false; - if(this.activePacketSize === -3) { - if(this.activeBuffer.readable < 1) { + if (this.activePacketSize === -3) { + if (this.activeBuffer.readable < 1) { return; } @@ -76,33 +76,34 @@ export class GameServerConnection { clearBuffer = true; } - if(this.activeBuffer.readable < this.activePacketSize) { + if (this.activeBuffer.readable < this.activePacketSize) { return; } // read packet data let packetData: ByteBuffer | null = null; - if(this.activePacketSize !== 0) { + if (this.activePacketSize !== 0) { packetData = new ByteBuffer(this.activePacketSize); - this.activeBuffer.copy(packetData, 0, this.activeBuffer.readerIndex, - this.activeBuffer.readerIndex + this.activePacketSize); + this.activeBuffer.copy(packetData, 0, this.activeBuffer.readerIndex, this.activeBuffer.readerIndex + this.activePacketSize); this.activeBuffer.readerIndex += this.activePacketSize; } - if(packetData && !handlePacket(this.player, this.activePacketId, this.activePacketSize, packetData)) { - logger.error(`Player packets out of sync for ${this.player.username}, resetting packet buffer...`, - `If you're seeing this, there's a packet that needs fixing. :)`); + if (packetData && !handlePacket(this.player, this.activePacketId, this.activePacketSize, packetData)) { + logger.error( + `Player packets out of sync for ${this.player.username}, resetting packet buffer...`, + `If you're seeing this, there's a packet that needs fixing. :)`, + ); clearBuffer = true; } - if(clearBuffer) { + if (clearBuffer) { this.activeBuffer = null; } this.activePacketId = null; this.activePacketSize = null; - if(this.activeBuffer !== null && this.activeBuffer.readable > 0) { + if (this.activeBuffer !== null && this.activeBuffer.readable > 0) { this.decodeMessage(); } } @@ -115,5 +116,4 @@ export class GameServerConnection { public closeSocket(): void { this.clientSocket.destroy(); } - } diff --git a/src/server/game/game-server.ts b/src/server/game/game-server.ts index 43265b5c1..ee12acd7d 100644 --- a/src/server/game/game-server.ts +++ b/src/server/game/game-server.ts @@ -1,37 +1,32 @@ import { logger } from '@runejs/common'; -import { parseServerConfig, SocketServer } from '@runejs/common/net'; +import { SocketServer, parseServerConfig } from '@runejs/common/net'; import { Filestore } from '@runejs/filestore'; -import { activateGameWorld } from '@engine/world'; -import type { GameServerConfig } from '@server/game/game-server-config'; -import { GatewayServer } from '@server/gateway/gateway-server'; import { loadCoreConfigurations, loadGameConfigurations, xteaRegions } from '@engine/config/config-handler'; import { loadPackets } from '@engine/net/inbound-packet-handler'; import { watchForChanges, watchSource } from '@engine/util/files'; - +import { activateGameWorld } from '@engine/world'; +import type { GameServerConfig } from '@server/game/game-server-config'; +import { GatewayServer } from '@server/gateway/gateway-server'; /** * The singleton instance containing the server's active configuration settings. */ export let serverConfig: GameServerConfig; - /** * The singleton instance referencing the game's asset file store. */ export let filestore: Filestore; - export const openGatewayServer = (host: string, port: number): void => { - SocketServer.launch( - 'Game Gateway Server', - host, port, socket => new GatewayServer(socket)); + SocketServer.launch('Game Gateway Server', host, port, socket => new GatewayServer(socket)); }; export async function setupConfig(): Promise { serverConfig = parseServerConfig(); - if(!serverConfig) { + if (!serverConfig) { logger.error('Unable to start server due to missing or invalid server configuration.'); return false; } @@ -43,22 +38,19 @@ export async function setupConfig(): Promise { return true; } - /** * Configures the game server, parses the asset file store, initializes the game world, * and finally spins up the game server itself. */ export async function launchGameServer(): Promise { const config = await setupConfig(); - if(!config) { + if (!config) { return; } await loadPackets(); - const world = await activateGameWorld(); - - + const world = await activateGameWorld(); - if(process.argv.indexOf('-fakePlayers') !== -1) { + if (process.argv.indexOf('-fakePlayers') !== -1) { world.generateFakePlayers(); } diff --git a/src/server/gateway/gateway-server.ts b/src/server/gateway/gateway-server.ts index 563039896..e78ac46ea 100644 --- a/src/server/gateway/gateway-server.ts +++ b/src/server/gateway/gateway-server.ts @@ -3,23 +3,20 @@ import { createConnection } from 'net'; import { logger } from '@runejs/common'; import { ByteBuffer } from '@runejs/common'; -import { parseServerConfig, SocketServer } from '@runejs/common/net'; +import { SocketServer, parseServerConfig } from '@runejs/common/net'; import { LoginResponseCode } from '@runejs/login-server'; -import { activeWorld } from '@engine/world'; -import { GameServerConnection } from '@server/game/game-server-connection'; -import type { GameServerConfig } from '@server/game/game-server-config'; import { Isaac } from '@engine/net/isaac'; +import { activeWorld } from '@engine/world'; import { Player } from '@engine/world/actor/player/player'; - +import type { GameServerConfig } from '@server/game/game-server-config'; +import { GameServerConnection } from '@server/game/game-server-connection'; const serverConfig = parseServerConfig(); export type ServerType = 'game_server' | 'login_server' | 'update_server'; - export class GatewayServer extends SocketServer { - private serverType: ServerType; private gameServerConnection: GameServerConnection; private loginServerSocket: Socket; @@ -31,7 +28,7 @@ export class GatewayServer extends SocketServer { } public initialHandshake(buffer: ByteBuffer): boolean { - if(this.serverType) { + if (this.serverType) { this.decodeMessage(buffer); return true; } @@ -42,11 +39,11 @@ export class GatewayServer extends SocketServer { const packetId = buffer.get('byte', 'u'); - if(packetId === 15) { + if (packetId === 15) { this.serverType = 'update_server'; this.updateServerSocket = createConnection({ host: serverConfig.updateServerHost, - port: serverConfig.updateServerPort + port: serverConfig.updateServerPort, }); this.updateServerSocket.on('data', data => this.clientSocket.write(data)); this.updateServerSocket.on('end', () => { @@ -54,15 +51,15 @@ export class GatewayServer extends SocketServer { }); this.updateServerSocket.on('error', () => { logger.error(`Update server error.`); - }) + }); this.updateServerSocket.setNoDelay(true); this.updateServerSocket.setKeepAlive(true); this.updateServerSocket.setTimeout(30000); - } else if(packetId === 14) { + } else if (packetId === 14) { this.serverType = 'login_server'; this.loginServerSocket = createConnection({ host: serverConfig.loginServerHost, - port: serverConfig.loginServerPort + port: serverConfig.loginServerPort, }); this.loginServerSocket.on('data', data => { this.parseLoginServerResponse(new ByteBuffer(data)); @@ -86,9 +83,9 @@ export class GatewayServer extends SocketServer { } public decodeMessage(buffer: ByteBuffer): void | Promise { - if(this.serverType === 'login_server') { + if (this.serverType === 'login_server') { this.loginServerSocket.write(buffer); - } else if(this.serverType === 'update_server') { + } else if (this.serverType === 'update_server') { this.updateServerSocket.write(buffer); } else { this.gameServerConnection?.decodeMessage(buffer); @@ -102,18 +99,18 @@ export class GatewayServer extends SocketServer { } private async parseLoginServerResponse(buffer: ByteBuffer): Promise { - if(!this.serverKey) { + if (!this.serverKey) { // Login handshake response const handshakeResponseCode = buffer.get('byte'); - if(handshakeResponseCode === 0) { + if (handshakeResponseCode === 0) { this.serverKey = BigInt(buffer.get('long')); } } else { // Login response const loginResponseCode = buffer.get('byte'); - if(loginResponseCode === LoginResponseCode.SUCCESS) { + if (loginResponseCode === LoginResponseCode.SUCCESS) { try { const clientKey1 = buffer.get('int'); const clientKey2 = buffer.get('int'); @@ -122,18 +119,17 @@ export class GatewayServer extends SocketServer { const passwordHash = buffer.getString(); const lowDetail = buffer.get('byte') === 1; - if(activeWorld.playerOnline(username)) { + if (activeWorld.playerOnline(username)) { // Player is already logged in! // @TODO move to login server buffer = new ByteBuffer(1); buffer.put(LoginResponseCode.ALREADY_LOGGED_IN); } else { this.serverType = 'game_server'; - await this.createPlayer([ clientKey1, clientKey2 ], - gameClientId, username, passwordHash, lowDetail ? 'low' : 'high'); + await this.createPlayer([clientKey1, clientKey2], gameClientId, username, passwordHash, lowDetail ? 'low' : 'high'); return; } - } catch(e) { + } catch (e) { this.gameServerConnection?.closeSocket(); logger.error(e); } @@ -144,28 +140,29 @@ export class GatewayServer extends SocketServer { this.clientSocket.write(buffer); } - private async createPlayer(clientKeys: [ number, number ], - gameClientId: number, - username: string, - passwordHash: string, - detail: 'high' | 'low'): Promise { + private async createPlayer( + clientKeys: [number, number], + gameClientId: number, + username: string, + passwordHash: string, + detail: 'high' | 'low', + ): Promise { const sessionKey: number[] = [ Number(clientKeys[0]), Number(clientKeys[1]), Number(this.serverKey >> BigInt(32)), - Number(this.serverKey) + Number(this.serverKey), ]; const inCipher = new Isaac(sessionKey); - for(let i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { sessionKey[i] += 50; } const outCipher = new Isaac(sessionKey); - const player = new Player(this.clientSocket, inCipher, outCipher, gameClientId, - username, passwordHash, detail === 'low'); + const player = new Player(this.clientSocket, inCipher, outCipher, gameClientId, username, passwordHash, detail === 'low'); this.gameServerConnection = new GameServerConnection(this.clientSocket, player); @@ -182,5 +179,4 @@ export class GatewayServer extends SocketServer { await player.init(); } - } diff --git a/src/server/runner.ts b/src/server/runner.ts index 152bdaafb..e2ecd43a6 100644 --- a/src/server/runner.ts +++ b/src/server/runner.ts @@ -1,51 +1,60 @@ import 'source-map-support/register'; +import { initErrorHandling } from '@engine/util/error-handling'; +import { activeWorld } from '@engine/world'; import { logger } from '@runejs/common'; import { launchLoginServer } from '@runejs/login-server'; import { launchUpdateServer } from '@runejs/update-server'; -import { activeWorld } from '@engine/world'; -import { initErrorHandling } from '@engine/util/error-handling'; import { launchGameServer } from '@server/game/game-server'; - const shutdownEvents = [ - 'SIGHUP', 'SIGINT', 'SIGQUIT', - 'SIGILL', 'SIGTRAP', 'SIGABRT', - 'SIGBUS', 'SIGFPE', 'SIGUSR1', - 'SIGSEGV', 'SIGUSR2', 'SIGTERM' + 'SIGHUP', + 'SIGINT', + 'SIGQUIT', + 'SIGILL', + 'SIGTRAP', + 'SIGABRT', + 'SIGBUS', + 'SIGFPE', + 'SIGUSR1', + 'SIGSEGV', + 'SIGUSR2', + 'SIGTERM', ]; let running: boolean = true; let type: 'game' | 'login' | 'update' = 'game'; -if(process.argv.indexOf('-login') !== -1) { +if (process.argv.indexOf('-login') !== -1) { type = 'login'; -} else if(process.argv.indexOf('-update') !== -1) { +} else if (process.argv.indexOf('-update') !== -1) { type = 'update'; } -shutdownEvents.forEach(signal => process.on(signal as any, () => { - if(!running) { - return; - } - running = false; +shutdownEvents.forEach(signal => + process.on(signal as any, () => { + if (!running) { + return; + } + running = false; - logger.warn(`${signal} received.`); + logger.warn(`${signal} received.`); - if(type === 'game') { - activeWorld?.shutdown(); - } + if (type === 'game') { + activeWorld?.shutdown(); + } - logger.info(`${type.charAt(0).toUpperCase()}${type.substring(1)} Server shutting down...`); - process.exit(0); -})); + logger.info(`${type.charAt(0).toUpperCase()}${type.substring(1)} Server shutting down...`); + process.exit(0); + }), +); initErrorHandling(); -if(type === 'game') { +if (type === 'game') { launchGameServer(); -} else if(type === 'login') { +} else if (type === 'login') { launchLoginServer(); -} else if(type === 'update') { +} else if (type === 'update') { launchUpdateServer(); } diff --git a/tsconfig.json b/tsconfig.json index ed36c521c..0f339032a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,24 +24,9 @@ "@server/*": ["src/server/*"], "@plugins/*": ["src/plugins/*"] }, - "types": [ - "jest", - "node" - ], - "lib": [ - "esnext", - "dom", - "dom.iterable", - "scripthost" - ] + "types": ["jest", "node"], + "lib": ["esnext", "dom", "dom.iterable", "scripthost"] }, - "include": [ - "src/**/*.js", - "src/**/*.ts", - "tests/**/*.js", - "tests/**/*.ts" - ], - "exclude": [ - "node_modules" - ] + "include": ["src/**/*.js", "src/**/*.ts", "tests/**/*.js", "tests/**/*.ts"], + "exclude": ["node_modules"] } From 32312bca74f09854f90f995c7843ddc04c6f28ce Mon Sep 17 00:00:00 2001 From: Borig Date: Sat, 1 Feb 2025 17:08:04 +1300 Subject: [PATCH 4/4] Update documentation and CI build task --- .github/workflows/build.yml | 11 ++++++++++- CONTRIBUTING.md | 6 ++++++ README.md | 5 +++++ package.json | 3 +++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b485b6fbf..e7e5890c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build Project +name: Check & Build Project on: pull_request: @@ -22,6 +22,15 @@ jobs: - name: Install Node Modules run: npm i + - name: Run Linter + run: npm run lint:fin + + - name: Run Formatter + run: npm run format:fin + + - name: Run Tests + run: npm run test:fin + - name: Run Typecheck run: npm run typecheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8c3e5b53..12d5f81a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,12 @@ RuneJS was created with the intention of utilizing JavaScript/TypeScript and Nod Ultimately if you're looking to contribute, it's best to check in with us on Discord to see if we're already working on a specific feature or have plans for it already. Add us at **Tyn#0001** +## Code Style + +Code style (linting and formatting) are handled by [Biome](https://biomejs.dev/). It is recommended that you install [the Biome extension for your IDE](https://biomejs.dev/guides/editors/first-party-extensions/). + +Running `npm run fin` will perform all necessary checks (linting, formatting, typechecking and tests). + ## Testing Unit tests can be written using Jest. To execute the test suite, run `npm test` diff --git a/README.md b/README.md index 70c5d3020..ec3c25f6f 100644 --- a/README.md +++ b/README.md @@ -48,3 +48,8 @@ Before running these commands, you must: * `npm run standalone` Launches all three servers concurrently without building * `npm run build:watch` Builds the application and watches for changes * `npm run build` Builds the application +* `npm run lint` Runs Biome in linting mode, use `lint:fix` to autofix +* `npm run format` Runs Biome in formatting mode, use `format:fix` to autofix +* `npm run test` Runs all tests with Jest +* `npm run typecheck` Typechecks the project +* `npm run fin` Combines lint:fix, format:fix, test and typecheck into a single command diff --git a/package.json b/package.json index 0c90cbc68..7a5d813bf 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,12 @@ "build": "rimraf dist && swc ./src -d dist --strip-leading-paths", "build:watch": "swc ./src -d dist -w --strip-leading-paths", "lint": "biome lint", + "lint:fin": "biome lint --write --diagnostic-level=error --reporter=summary", "lint:fix": "biome lint --write", "format": "biome format", + "format:fin": "biome format --write --reporter=summary", "format:fix": "biome format --write", + "fin": "npm run typecheck && npm run lint:fin && npm run format:fin && npm run test:fin", "test": "jest", "test:fin": "jest --silent --reporters=\"summary\"", "typecheck": "tsc -p ./ --noEmit"